为什么模板参数推断在这里不起作用?

时间:2009-08-12 20:21:56

标签: c++ templates

我创建了两个简单的函数来获取模板参数和一个定义类型的空结构:

//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;
}

参数类型应用于struct S以获取引用。我用一些整数值调用它们但编译器无法推断出参数:

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

错误1错误C2783:'A   temp(S :: type)':无法演绎   'A'的模板参数

     

错误2错误C2783:'B   temp2(S :: type,B)':不能   推导出'A'的模板参数


为什么会这样?是否很难看到模板参数是 char int 值?

3 个答案:

答案 0 :(得分:29)

正如首先注意的那样,当您提及依赖名称时,会使用typename名称。所以你在这里不需要它。


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

关于模板实例化,问题是typename S<A>::type表征A的 nondeduced 上下文。当模板参数仅用于非弱化上下文时(函数中A的情况) )模板参数推导没有考虑到它。详情见C ++标准(2003)第14.8.2.4节。

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


temp<char>(c);

答案 1 :(得分:8)

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

  

非弱势语境是:

     
      
  • 使用 qualified-id 指定的类型的嵌套名称说明符
  •   
  • template-id 的类型,其中一个或多个 template-arguments 是一个引用 template-parameter
  •   
     

如果以包含非弱化上下文的方式指定类型名称,则包含该类型名称的所有类型也不会受到限制。但是,复合类型可以包括推导类型和非推导类型。 [示例:如果类型指定为A<T>::B<T2>,则TT2都不受限制。同样,如果某个类型指定为A<I+J>::X<T>,则IJT不会被限制。如果将类型指定为void f(typename A<T>::B, A<T>),则T中的A<T>::B未受到限制,但推导出T中的A<T>。 ]

答案 2 :(得分:5)

扣除工作向前发展:

template <class T> void f(T);

f(2); // can deduce int from T
  

为什么会这样?

它不向后退(你的例子):

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

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

模板演绎可以做一些神奇的(Turing-complete)事情,但我不认为这是其中之一。

您可能会使用类似(未经测试)的内容:

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

    ...
}

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