35

以下代码有什么问题?

#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.
4

3 回答 3

53

中的论点Kconst typename A<K>::X不可演绎的。基本上, a 剩下的所有内容::都是不可演绎的(如果::分隔嵌套名称)。

通过运行这个思想实验来了解为什么要求推理没有意义是微不足道的:

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),可能有许多环境类型是嵌套类型,或者不需要任何类型。

于 2012-09-24T13:39:48.757 回答
9
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/4

然而,在某些上下文中,该值不参与类型推导,而是使用模板参数的值,这些值要么在别处推导,要么显式指定。如果模板参数仅在非推导上下文中使用且未明确指定,则模板参数推导失败

n3337 14.8.2.5/5

未推断的上下文是:

— 使用限定 ID 指定的类型的嵌套名称说明符。

于 2012-09-24T13:40:00.393 回答
0

首先,::用于引用嵌套结构是不正确的。正确的方法是使用A<K>.xwherex是 type 的成员X<K>。但要使其正常工作,您需要分别声明两个类型为 和x的成员。yX<K>Y<K>

其次,我认为一个好的做法是将模板声明struct Xstruct Ystruct A的声明分开,以避免嵌套的struct声明。

简而言之,我会将您的代码重写如下:

template<class K>
struct X {
    K p;
};

template<class K>
struct Y {
    K q;
};

template<class K>
struct A {
    X<K> x;
    Y<K> y;
};

template<class K>
void foo(const X<K>& x, const Y<K>& y) {
    std::cout << "A" << std::endl;
}

int main() {
    A<float> a;
    foo(a.x, a.y);
    return 0;
}
于 2020-01-02T10:50:52.063 回答