无法为模板化的朋友找出 VS2019 中的链接器错误 class

Can't figure out linker error in VS2019 for friend in templated class

请注意 - Whosebug 找到了十几个与此类似的示例。我遍历了每一个,但仍然无法编译我的代码。这可能与另一个问题类似,但如果您说是 - 请确保示例中显示的技术允许编译 this 代码。提前致谢。

作为一名 C++ 学生,我正在研究一些基本代码,希望能做得更好。我确定这是一个简单的 error/mistake,但我无法弄明白:

#include <iostream>
#include <string>

// General templated class
template <typename T>
class AddElements {
private:
    T lhs;
    T rhs;
public:
    AddElements(T lhs_init=T(), T rhs_init=T()): lhs{lhs_init}, rhs{rhs_init} { }
    T add() { return lhs + rhs; }

    friend std::istream& operator>>(std::istream&, const AddElements&);
};

template <typename T>
std::istream& operator>>(std::istream& istr, const AddElements<T>& ae) {
    istr >> ae.lhs;
    istr >> ae.rhs;
    return istr;
}

int main() {
    std::size_t lines;
    std::string line_types;
    AddElements<int> mycol_ints;

    std::cin >> lines;
    std::cin >> mycol_ints;

    return 0;
}

我正在使用 Visual Studio 2019 年的 C++ 编译器:

$env:cl = "/EHsc /Wall /external:anglebrackets /external:W3 /external:templates- /experimental:external /RTCsu /sdl /analyze /std:c++17"

cl classtemplates.cpp
(...)
/out:classtemplates.exe
classtemplates.obj
classtemplates.obj : error LNK2019: unresolved external symbol "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl operator>>(class std::basic_istream<char,struct std::char_traits<char> > &,class AddElements<int> const &)" (??5@YAAAV?$basic_istream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$AddElements@H@@@Z) referenced in function _main
classtemplates.exe : fatal error LNK1120: 1 unresolved externals

欢迎指点精品手册。我花了一段时间在谷歌上搜索并查看 cppreference.com 上的示例,但现在我被难住了。

友元声明是指非模板运算符,而定义是模板运算符,两者不匹配。

你可能想要

template <typename T>
class AddElements;
template <typename T>
std::istream& operator>>(std::istream& istr, AddElements<T>& ae);

template <typename T>
class AddElements {
private:
    T lhs;
    T rhs;
public:
    AddElements(T lhs_init=T(), T rhs_init=T()): lhs{lhs_init}, rhs{rhs_init} { }
    T add() { return lhs + rhs; }

    friend std::istream& operator>> <>(std::istream&, AddElements&);
    //                              ^^
    // refer to the instantiation of the template operaotr>>
};

template <typename T>
std::istream& operator>>(std::istream& istr, AddElements<T>& ae) {
    istr >> ae.lhs;
    istr >> ae.rhs;
    return istr;
}

或者您可以使其成为非模板并在 class

中内联定义它
template <typename T>
class AddElements {
private:
    T lhs;
    T rhs;
public:
    AddElements(T lhs_init=T(), T rhs_init=T()): lhs{lhs_init}, rhs{rhs_init} { }
    T add() { return lhs + rhs; }

    friend std::istream& operator>> (std::istream& istr, AddElements& ae) {
        istr >> ae.lhs;
        istr >> ae.rhs;
        return istr;
    }
};

顺便说一句:参数 ae 应该声明为非常量;它应该在 operator>>.

中修改