如何使用代理 class 和模板将 "simulate" 函数重载 return 值?
How to use proxy class and template to "simulate" function overload by return value?
我会尝试挖掘更多的 C++ 模板和类型系统知识,我知道通过重载 Type.Operator(),它看起来像 "overload" 由 return 类型,
#include<iostream>
using namespace std;
class My{
int getInt() const {return 20;}
short getShort() const {return 3;}
public:
template<class T>
T get() const
template<int>
int get() const {return getInt();}
template<short>
short get() const {return getShort();}
};
struct Proxy{
My const* myOwner;
Proxy(My const* owner):myOwner(owner){}
operator int() const {return myOwner->getInt();}
operator short() const {return myOwner->getShort();}
};
int main(){
My m;
Proxy p(&m);
int _i = p;//works!
short _s = p;//works!
cout<<_i<<","<<_s<<",\n";
// How to use template My::get
int i = m.get(); // doesn't compile
short s = m.get(); // doesn't compile
cout<<i<<","<<s<<",\n";
return 0;
}
我希望有一些方法可以使下面几行根据 return 类型进行不同的函数调用:
int i = m.get();
short s = m.get();
如何实现?非常感谢。
您可以像这样使用 SFINAE:
template <typename T,
typename std::enable_if<std::is_same<T, int>::value>::type* = nullptr>
int get() const {
return getInt();
}
template <typename T,
typename std::enable_if<std::is_same<T, short>::value>::type* = nullptr>
short get() const {
return getShort();
}
然后在Proxy
class中调用上面的函数如:
operator int() const {
return myOwner->get<int>();
}
operator short() const {
return myOwner->get<short>();
}
在主函数中:
int i = m.get<int>();
short s = m.get<short>();
注意:函数 return 值被分配给 int
或 short
的事实未在模板中使用参数扣除.
... to "simulate" function overload by return value?
忽略示例的所有样板文件并只关注这个问题,您可以定义一个主模板函数并删除(主模板)定义,然后添加显式(完整) 此函数的特化仅适用于您想要 "overload":
的类型
#include <cstdint>
template <typename T>
T get() = delete;
template<>
uint8_t get<uint8_t>() { return 42U; } // or delegate to getUint8().
template<>
uint32_t get<uint32_t>() { return 43U; }
template<>
float get<float>() { return 44.5F; }
int main() {
const auto a = get<uint8_t>();
const auto b = get<uint32_t>();
const auto c = get<float>();
// const auto d = get<uint16_t>(); // error: use of deleted function
}
但是请注意,您需要明确指定单一类型模板参数的类型,因为没有 get()
的参数可用于模板参数推导。
如果我理解您的目标,那么您的实现(以及其他必要的修复)中缺少的是 My
的成员函数,它实际上 returns 一个 Proxy
.
类似于以下内容(可测试 here)
#include<iostream>
class Proxy;
class My
{
public:
template<class T = Proxy> // <--
T get() const;
};
class Proxy
{
My const& owner_;
public:
Proxy(My const& owner) : owner_(owner)
{}
operator int() const;
operator short() const;
};
template<>
Proxy My::get<Proxy>() const {
return *this; // <---
}
template<>
int My::get<int>() const {
return 20;
}
template<>
short My::get<short>() const {
return -3;
}
Proxy::operator int() const {
return owner_.get<int>();
}
Proxy::operator short() const {
return owner_.get<short>();
}
int main()
{
My m;
int i = m.get<int>();
short s = m.get<short>();
std::cout << i << ", " << s << '\n';
int i_ = m.get();
short s_ = m.get();
std::cout << i_ << ", " << s_ << '\n';
}
我会尝试挖掘更多的 C++ 模板和类型系统知识,我知道通过重载 Type.Operator(),它看起来像 "overload" 由 return 类型,
#include<iostream>
using namespace std;
class My{
int getInt() const {return 20;}
short getShort() const {return 3;}
public:
template<class T>
T get() const
template<int>
int get() const {return getInt();}
template<short>
short get() const {return getShort();}
};
struct Proxy{
My const* myOwner;
Proxy(My const* owner):myOwner(owner){}
operator int() const {return myOwner->getInt();}
operator short() const {return myOwner->getShort();}
};
int main(){
My m;
Proxy p(&m);
int _i = p;//works!
short _s = p;//works!
cout<<_i<<","<<_s<<",\n";
// How to use template My::get
int i = m.get(); // doesn't compile
short s = m.get(); // doesn't compile
cout<<i<<","<<s<<",\n";
return 0;
}
我希望有一些方法可以使下面几行根据 return 类型进行不同的函数调用:
int i = m.get();
short s = m.get();
如何实现?非常感谢。
您可以像这样使用 SFINAE:
template <typename T,
typename std::enable_if<std::is_same<T, int>::value>::type* = nullptr>
int get() const {
return getInt();
}
template <typename T,
typename std::enable_if<std::is_same<T, short>::value>::type* = nullptr>
short get() const {
return getShort();
}
然后在Proxy
class中调用上面的函数如:
operator int() const {
return myOwner->get<int>();
}
operator short() const {
return myOwner->get<short>();
}
在主函数中:
int i = m.get<int>();
short s = m.get<short>();
注意:函数 return 值被分配给 int
或 short
的事实未在模板中使用参数扣除.
... to "simulate" function overload by return value?
忽略示例的所有样板文件并只关注这个问题,您可以定义一个主模板函数并删除(主模板)定义,然后添加显式(完整) 此函数的特化仅适用于您想要 "overload":
的类型#include <cstdint>
template <typename T>
T get() = delete;
template<>
uint8_t get<uint8_t>() { return 42U; } // or delegate to getUint8().
template<>
uint32_t get<uint32_t>() { return 43U; }
template<>
float get<float>() { return 44.5F; }
int main() {
const auto a = get<uint8_t>();
const auto b = get<uint32_t>();
const auto c = get<float>();
// const auto d = get<uint16_t>(); // error: use of deleted function
}
但是请注意,您需要明确指定单一类型模板参数的类型,因为没有 get()
的参数可用于模板参数推导。
如果我理解您的目标,那么您的实现(以及其他必要的修复)中缺少的是 My
的成员函数,它实际上 returns 一个 Proxy
.
类似于以下内容(可测试 here)
#include<iostream>
class Proxy;
class My
{
public:
template<class T = Proxy> // <--
T get() const;
};
class Proxy
{
My const& owner_;
public:
Proxy(My const& owner) : owner_(owner)
{}
operator int() const;
operator short() const;
};
template<>
Proxy My::get<Proxy>() const {
return *this; // <---
}
template<>
int My::get<int>() const {
return 20;
}
template<>
short My::get<short>() const {
return -3;
}
Proxy::operator int() const {
return owner_.get<int>();
}
Proxy::operator short() const {
return owner_.get<short>();
}
int main()
{
My m;
int i = m.get<int>();
short s = m.get<short>();
std::cout << i << ", " << s << '\n';
int i_ = m.get();
short s_ = m.get();
std::cout << i_ << ", " << s_ << '\n';
}