我有一个像这样的函数定义
template <typename T>
auto print(T t) -> decltype(t.print()) {
return t.print();
}
这个想法是参数必须是T类型,并且必须具有print函数.这个打印功能可以返回任何内容,解释了decltype的需要.例如,您可以这样做:
struct Foo
{
int print()
{
return 42;
}
};
struct Bar
{
std::string print()
{
return "The answer...";
}
};
...
std::cout << print(Foo()) << std::endl;
std::cout << print(Bar()) << std::endl;
/* outputs:
42
The answer...
*/
我读到模板不能进行运行时实例化,并且您可以从类派生类,然后确定它们的类型以查看要使用的模板参数.但是,我如何为非类型类型执行此操作?这个想法是能够:
template <typename T>
T print(T t) {
return t;
}
同样,但这给了我模糊的过载错误.资格认证不起作用,即打印< Foo>.另一个得到的问题是,如果我有一个类似的仿函数:
struct Foo
{
virtual int print();
operator int() const
{
return 42;
}
};
它现在如何决定?
所以我的问题是,是否可以使用模板解决所有这些歧义,或者我是否必须编写一堆冗余代码?
测试
我逐步添加测试,从下面复制/粘贴每个编辑的解决方案.结果如下:
使用以下课程:
struct Foo
{
int print()
{
return 42;
}
operator int() const
{
return 32;
}
};
struct Bar
{
std::string print()
{
return "The answer...";
}
operator int() const
{
return (int)Foo();
}
};
struct Baz
{
operator std::string() const
{
return std::string("The answer...");
}
};
以下测试输出:
std::cout << print(Foo()) << std::endl;
std::cout << print(Bar()) << std::endl;
std::cout << print(42) << std::endl;
std::cout << print((int)Foo()) << std::endl;
std::cout << print("The answer...") << std::endl;
std::cout << print(std::string("The answer...")) << std::endl;
std::cout << print((int)Bar()) << std::endl;
std::cout << print((std::string)Baz()) << std::endl;
两者都正确输出:
42
The answer...
42
32
The answer...
The answer...
32
The answer...
解决方法:
您可以采用以下方法,如果存在这样的成员函数,则在输入上调用print()成员函数,否则它将返回输入本身:
namespace detail
{
template<typename T, typename = void>
struct print_helper
{
static T print(T t) {
return t;
}
};
template<typename T>
struct print_helper<T, decltype(std::declval<T>().print(), (void)0)>
{
static auto print(T t) -> decltype(t.print()) {
return t.print();
}
};
}
template<typename T>
auto print(T t) -> decltype(detail::print_helper<T>::print(t))
{
return detail::print_helper<T>::print(t);
}
这是一个live example.