为什么模板论证扣除在这里不起作用?

我创build了两个获取模板参数的简单函数和一个定义types的空结构:

//S<T>::type results in T& template <class T> struct S { typedef typename T& type; }; //Example 1: get one parameter by reference and return it by value template <class A> A temp(typename S<A>::type a1) { return a1; } //Example 2: get two parameters by reference, perform the sum and return it template <class A, class B> B temp2(typename S<A>::type a1, B a2)//typename struct S<B>::type a2) { return a1 + a2; } 

参数types被应用到结构S以获得引用。 我用一些整数值调用它们,但是编译器无法推导出这些参数:

 int main() { char c=6; int d=7; int res = temp(c); int res2 = temp2(d,7); } 

错误1错误C2783:'临时(S ::types)':无法推断出'A'的模板参数

错误2错误C2783:'B temp2(S :: type,B)':无法推断出'A'的模板参数


为什么发生这种情况? 难以看出模板参数是charint值吗?

就像第一个注意事项一样,当您提到一个依赖名称时,使用了typename name。 所以你不需要这里

 template <class T> struct S { typedef T& type; }; 

关于模板实例化,问题在于typename S<A>::type表示A的非诱致上下文。当一个模板参数仅用于非诱致上下文(函数A中的情况)时,不考虑模板论证扣除。 细节在C ++标准(2003)的14.8.2.4节。

要使您的通话有效,您需要明确指定types:

 temp<char>(c); 

这看起来像非诱惑的上下文。 根据C ++标准14.8.2.4/4:

非诱骗的情况是:

  • 使用限定标识 指定的types的嵌套名称说明符。
  • 一个types,它是一个template-id ,其中一个或多个模板参数是引用模板参数的expression式。

当一个types名称被指定的方式包含一个nondeduced上下文时,包含该types名称的所有types也都是非导出的。 但是,复合types可以包括推导types和非推导types。 [ 例如 :如果一个types被指定为A<T>::B<T2> ,那么TT2都是非导出的。 同样,如果一个types被指定为A<I+J>::X<T> ,则IJT是非导致的。 如果一个types被指定为void f(typename A<T>::B, A<T>) ,则A<T>::B中的T是非导致的,但是推导出A<T>A<T> ]

扣除工作的前进方向:

 template <class T> void f(T); f(2); // can deduce int from T 

为什么发生这种情况?

它不能在反向工作(你的例子):

 template <class A> void g(typename S<A>::type); 

难以看出模板参数是char和int值吗?

模板扣除可以做一些神奇的(图灵完成)的东西,但我不认为这是其中之一。

你可以使用像(未经testing)的东西:

 template <class SA> void h(SA a1) { STATIC_ASSERT(same_type<SA, S<A>::type>::value); typedef typename SA::type A; ... } 

使用你最喜欢的静态断言库(Boost有两个)。