Не могу понять ошибку компоновщика в VS2019 для друга в шаблонном классе - PullRequest
1 голос
/ 28 апреля 2020

Обратите внимание: StackOverflow нашел дюжину похожих на этот пример примеров. Я прошел через все и до сих пор не могу заставить мой код скомпилироваться. Это может быть похоже на другой вопрос, но если вы скажете, что это так - пожалуйста, убедитесь, что методы, показанные в примере, позволяют получить этот код для компиляции. Заранее спасибо.

Я играю с некоторым базовым c кодом, пытаясь стать лучше, изучая C ++. Я уверен, что это простая ошибка / ошибка, но я не могу понять:

#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;
}

Я использую компилятор C ++ Visual Studio 2019:

$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, но сейчас я в замешательстве.

1 Ответ

1 голос
/ 28 апреля 2020

Объявление друга относится к не шаблонному оператору, в то время как определение является оператором шаблона, они не совпадают.

Возможно, вы захотите

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;
}

Или вы можете сделать он не шаблонный и определите его встроенным в классе

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

...