如何使以下代码正常工作?
非模板版本编译完美,但模板版本惨败。为什么模板版本无法确定要调用哪个函数版本以及如何修复它?我想过添加到隐式转换为 BT 的模板类 AT 运算符,但它也不起作用。
class A {};
class B
{
public:
B(A){};
};
void func(B){};
template<typename T>
class AT {};
template<typename T>
class BT
{
public:
BT(AT<T>){};
};
template<typename T>
void funcT(BT<T>){};
int main()
{
func(A{});
funcT(AT<int>{}); // unable to deduce the funcT template argument
funcT<int>(AT<int>{}); // compiles but I don't want to write that
return 0;
}
有一些愚蠢的修复,例如编写接受AT<T>
并将其转换为BT<T>
的函数版本。但是当一切都应该按原样工作时,我不想编写一堆函数。如果这是一个模棱两可的电话,我可以理解它......
模板参数推导中不考虑隐式转换:
类型推断不考虑隐式转换(上面列出的类型调整除外(:这是重载解决的工作,稍后会发生。
这意味着,对于期望BT<T>
但通过了AT<int>
funcT
,T
无法推断,并且无法调用。
如您所显示的,解决方法是显式指定模板参数以绕过模板参数推导。
非模板函数没有这样的问题;它们不需要模板参数推导。
另一个答案解释了发生了什么,但有一种方法可以解决这个问题
template<class T, template<class>class Temp, typename std::enable_if<std::is_convertible< Temp<T>, BT<T>>::value, bool>::type = true>
void funcT(Temp<T> t) {
auto bt = static_cast<BT<T>>(t);
}
这可以由具有相同行为的fooT(A<int>{});
调用fooT(B<int>{});
调用。