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

C++ 为什么模板参数推断在这里不起作用?,c++,templates,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

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

//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;
}
错误1错误C2783:“A 临时(S::type)“”无法推断 “A”的模板参数

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



为什么会这样?很难看出模板参数是char和int值吗?

正如第一个注意事项,当您提到依赖名称时,会使用typename name。所以你在这里不需要它


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

模板
结构
{
typedef T&type;
};
关于模板实例化,问题在于
typename S::type
为a描述了非派生上下文的特征。当模板参数仅在非派生上下文中使用(函数中的a的情况)时,模板参数推导不考虑它。详细内容在C++标准(2003)的第14.2.4节。 要使呼叫正常工作,需要显式指定类型:


temp<char>(c);

温度(c);

它看起来像非派生上下文。C++标准14.2.2.4/4:

非派生上下文包括:

  • 使用限定id指定的类型的嵌套名称说明符
  • 一种模板id类型,其中一个或多个模板参数是引用模板参数的表达式
当以包含非派生上下文的方式指定类型名时,构成该类型名的所有类型也都是非派生的。但是,复合类型可以包括派生类型和非派生类型。[示例:如果将类型指定为
a::B
,则
T
T2
都是非派生的。同样,如果将类型指定为
a::X
I
J
T
则是非派生的。如果将类型指定为
void f(typename a::B,a)
A::B
中的
T
是非推导的,但是
A
中的
T
是推导的。]


未来方向的扣除工作:

template <class T> void f(T);

f(2); // can deduce int from T
模板无效f(T);
f(2);//可以从T推断int
为什么会这样

它不能反向工作(您的示例):

template void g(typename S::type);
很难看出模板参数是char和int值吗

模板演绎可以做一些神奇的事情(图灵完成),但我不认为这是其中之一

您可以使用(未经测试的):

模板空白h(SA a1)
{
静态断言(相同类型::值);
typedef typename SA::type A;
...
}

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

您能用简单的文字和示例向我解释一下吗:
使用限定id指定的类型的嵌套名称说明符。
我知道嵌套名称说明符是
X:
,限定id是以
为前缀的类型,但无法总结或理解整个事情。非常感谢:)它类似于使用限定id指定的`(类型的嵌套名称说明符)`还是`(使用限定id指定的类型的嵌套名称说明符)``
template <class T> void f(T);

f(2); // can deduce int from T
template <class A> void g(typename S<A>::type);
template <class SA> void h(SA a1)
{
    STATIC_ASSERT(same_type<SA, S<A>::type>::value);
    typedef typename SA::type A;

    ...
}