1

为什么我会收到以下链接器错误?

template<typename T, typename U>
class A {
public:
    class B;
};

template<typename T, typename U>
class A<T, U>::B {
    friend bool operator==(const B& b1, const B& b2);
};

template<typename T, typename U>
bool operator==(const typename A<T, U>::B& b1, const typename A<T, U>::B& b2) {
    return true;
}

int main() {
    A<char, int>::B b1;
    A<char, int>::B b2;

    if (b1 == b2) {
        return 0;
    } else {
        return 1;
    }
}

我得到的错误是:

Undefined symbols for architecture x86_64:
  "operator==(A<char, int>::B const&, A<char, int>::B const&)", referenced from:
      _main in test-qSCyyF.o
4

1 回答 1

2

因为你在调用它并且它没有定义!

这个

template<typename T, typename U>
class A<T, U>::B {
    friend bool operator==(const B& b1, const B& b2);
};

是类的非模板友元函数的声明A<T,U>::B

它与调用(b1 == b2)以及您在下面定义的模板运算符一样匹配,但它是首选,因为它是非模板。

GCC甚至发出警告-Wnon-template-friend

警告:朋友声明 'bool operator==(const A::B&, const A::B&)' 声明了一个非模板函数 [-Wnon-template-friend]
注意:(如果这不是您想要的,请确保函数模板已经被声明并在函数名后面添加<>)

为了解决这个问题,它提供了定义

template<typename T, typename U>
class A<T, U>::B {
    friend bool operator==(const B& b1, const B& b2) {
        return true;
    }
};

并摆脱模板化运算符或仅保留模板之一。

于 2013-08-01T19:45:46.013 回答