以下代码有什么问题?
#include <iostream>
template<typename K>
struct A {
struct X { K p; };
struct Y { K q; };
};
template<typename K>
void foo(const typename A<K>::X& x, const typename A<K>::Y& y) {
std::cout << "A" << std::endl;
}
int main() {
A<float>::X x;
A<float>::Y y;
foo(x, y);
}
clang给出以下错误消息:
17:2: error: no matching function for call to 'foo'
foo(x, y);
^~~
10:6: note: candidate template ignored: couldn't infer template argument 'K'
void foo(const typename A<K>::X& x, const typename A<K>::Y& y) {
^
1 error generated.
答案 0 :(得分:48)
K
中的参数const typename A<K>::X
不可扣除。基本上,::
左边的所有内容都不可推导(如果::
分隔嵌套名称)。
通过这个思想实验来了解为什么要求扣除是没有意义的,这是微不足道的:
struct A { typedef int type; }
struct B { typedef int type; }
template <typename T> void foo(typename T::type);
foo(5); // is T == A or T == B ??
从类型到嵌套类型没有一对一的映射:给定任何类型(例如int
),可能有许多环境类型,它是嵌套类型,或者不需要任何
答案 1 :(得分:8)
template<typename K>
void foo(const typename A<K>::X& x, const typename A<K>::Y& y) {
std::cout << "A" << std::endl;
}
K
无法推断,因为它位于non-deduced
上下文中。
但是,在某些情况下, 该值不参与类型推导,而是使用模板参数的值 在其他地方推断或明确指定。 如果模板参数仅在非推导中使用 上下文并未明确指定,模板参数推断失败。
n3337 14.8.2.5/5
未推断的上下文是:
- 使用qualified-id指定的类型的嵌套名称说明符。
答案 2 :(得分:0)
首先,使用::
引用嵌套结构是不正确的。正确的方法是使用A<K>.x
,其中x
是类型X<K>
的成员。但这要起作用,您需要声明两个成员x
,类型y
和X<K>
的{{1}}。
第二,我认为一种好的做法是将Y<K>
和struct X
的模板声明与struct A的声明分开,以避免嵌套的struct声明。
简而言之,我将您的代码重写如下:
struct Y