我尝试编译以下代码行,但它失败了:
template <typename T>
struct InputBlockParameterType {
typedef T type;
};
template <typename T, template <typename> class BlockTypeTrait>
struct BlockParameterImpl {
typedef typename BlockTypeTrait<T>::type type;
};
template <typename T>
struct InputBlockParameter {
typedef typename BlockParameterImpl<T, InputBlockParameterType>::type type;
};
struct Functor {
template <typename T>
bool operator()(typename InputBlockParameter<T>::type p) {
return true;
}
};
int main() {
InputBlockParameter<double>::type arg = 0.0;
Functor f;
f(arg);
return 0;
}
错误是(MSVC 2013):
1>main.cpp(31): error C2783: 'bool Functor::operator ()(InputBlockParameter<T>::type)' : could not deduce template argument for 'T'
1> main.cpp(21) : see declaration of 'Functor::operator ()'
如果我将仿函数更改为
struct Functor {
template <typename T>
bool operator()(T p) {
return true;
}
};
一切都按预期编译好。
为什么代码的第一个版本没有编译?它是在标准中定义的某个地方吗?
答案 0 :(得分:4)
扣除仅适用于推断的背景。
哪个没用:X仅在X工作时有效。我可以引用标准,但它只是说“是的,那不起作用”更难以阅读散文。
考虑它的最好方法是编译器只进行模式匹配。但是,它不会搜索或尝试反转您编写的任何类型映射。
foo<T>::type
可以进行图灵完成计算(最高可达编译器限制),从T
转到type
:因此标准声明使用T
一个非推导的上下文,即使foo
类型的地图似乎很容易反转给你。反编任意函数对于要求编译器来说并不实际,即使我们已经要求它们完成Turing以便编译C ++。
编译器不会转换(除了base和cv剥离和参数衰减),或者在模板类型推导期间反转类型映射。它只是模式匹配参数。
它将遵循SFINAE目的的类型地图,但这在理论上要容易得多。
如果您可以自己编写逆映射,可以使用SFINAE和默认参数以及模板类专门化和转发的混合来获得您可能想要的效果。