我有一个像这样的函数定义
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...