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

Jua*_*uan 24 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;
}
Run Code Online (Sandbox Code Playgroud)

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

int main()
{
    char c=6;
    int d=7;
    int res = temp(c);
    int res2 = temp2(d,7);
}
Run Code Online (Sandbox Code Playgroud)

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

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


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

Lea*_*elo 29

与第一个注意事项一样,当您提及从属名称时,将使用typename 名称.所以你在这里不需要它.


template <class T>
struct S
{
    typedef T& type;
};
Run Code Online (Sandbox Code Playgroud)

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

要使您的呼叫起作用,您需要明确指定类型:


temp<char>(c);
Run Code Online (Sandbox Code Playgroud)


Kir*_*sky 8

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

非受限的上下文是:

  • 使用qualified-id 指定的类型的嵌套名称说明符.
  • 一种类型,它是一个template-id,其中一个或多个template-arguments是一个引用模板参数的表达式.

如果以包含非损坏上下文的方式指定类型名称,则包含该类型名称的所有类型也都是非限定的.但是,复合类型可以包括推导类型和非推导类型.[ 实施例:如果一个类型被指定为A<T>::B<T2>,两者TT2是nondeduced.同样地,如果一个类型被指定为A<I+J>::X<T>,I,J,和T是nondeduced.如果将类型指定为void f(typename A<T>::B, A<T>),则Tin A<T>::B为nondeuced但Tin A<T>推导出.]


Mar*_*Ray 5

扣除在前进方向:

template <class T> void f(T);

f(2); // can deduce int from T
Run Code Online (Sandbox Code Playgroud)

为什么会这样?

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

template <class A> void g(typename S<A>::type);
Run Code Online (Sandbox Code Playgroud)

是否很难看到模板参数是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;

    ...
}
Run Code Online (Sandbox Code Playgroud)

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