【发布时间】:2013-05-12 08:43:19
【问题描述】:
我有一个这样的函数定义
template <typename T>
auto print(T t) -> decltype(t.print()) {
return t.print();
}
想法是参数必须是T 类型并且必须具有print 函数。这个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...
*/
我读到模板不能进行运行时实例化,您可以让类派生自基类,然后确定它们的类型以查看要使用的模板参数。但是,我将如何为 non-class 类型执行此操作?我们的想法是能够:
template <typename T>
T print(T t) {
return t;
}
也是如此,但这给了我模棱两可的过载错误。排位赛不起作用,即print<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...
【问题讨论】:
-
这是SFINAE 的案例。简而言之:您仅为那些具有
T::print()的类型定义您的第一个实现,而为所有其他情况定义第二个实现。另一种选择是使用您想要支持但没有打印功能的所有类型手动重载您的函数,例如:int print(int);
标签: c++ templates c++11 decltype