繁体   English   中英

C ++朋友模板功能-minGW错误,但不包含VS2015

[英]C++ friend template function - minGW error but not VS2015

以下代码可以在Visual Studio 2015中正常编译,但使用minGW可以得到下面显示的警告和错误:

#include <iostream>
using std::ostream;

template<typename ElemType, int SIZE>
class Array
{
    friend ostream &operator<<(ostream &out, const Array<ElemType, SIZE> &value);

    ElemType operator[](int index) const;

private:
    ElemType elements[SIZE];
};

template<typename ElemType, int SIZE>
ostream &operator<<(ostream &out, const Array<ElemType, SIZE> &value);

template<typename ElemType, int SIZE>
ostream &operator<<(ostream &out, const Array<ElemType, SIZE> &value)
{
    out << elements[0];
    return out;
}

mingw32-g++.exe -Wall -g -pedantic-errors -pedantic -Wextra -Wall -std=c++98 -c Test.cpp
Test.cpp:7:79: warning: friend declaration 'std::ostream& operator<<(std::ostream&, const Array<ElemType, SIZE>&)' declares a non-template function [-Wnon-template-friend]
Test.cpp:7:79: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) 
Test.cpp: In function 'std::ostream& operator<<(std::ostream&, const Array<ElemType, SIZE>&)':
Test.cpp:21:11: error: 'elements' was not declared in this scope

我距离其中一些专家还很遥远,所以我不确定是什么问题。 似乎是在告诉我,它需要在类本身的朋友声明之前的跟随代码,但是当我将其放在那里时,会导致其他编译错误:

template<typename ElemType, int SIZE>

提前致谢!

进行@Trevor Hickey在其帖子中建议的更改后,关于朋友模板功能的警告消失了。 但是,我仍然收到有关未在作用域中声明“元素”(在朋友函数中)的错误。

您正在使用该类中的模板参数,但是该函数本身不是模板函数。 如定义中所示,它必须是模板函数。

#include <iostream>
using std::ostream;

template<typename ElemType, int SIZE>
class Array
{
    template<typename T, int U>
    friend ostream &operator<<(ostream &out, const Array<T, U> &value);

    ElemType operator[](int index) const;

private:
    ElemType elements[SIZE];
};

template<typename ElemType, int SIZE>
ostream &operator<<(ostream &out, const Array<ElemType, SIZE> &value)
{
    out << value.elements[0];
    return out;
}

您的代码中有两个独立的问题。 比较容易的是out << elements[0]; 应该out << value.elements[0]; 这是因为您要打印作为参数value成员的元素。 请记住,我们这里是一个非成员函数,没有this函数,没有成员可以使用非限定名称访问。

另一个称为模板朋友问题 到目前为止,您只会收到警告,但如果尝试编译完整的程序,则会收到错误消息。 我添加了代码:

int main() { Array<int, 5> a; std::cout << a; }

并出现错误:

undefined reference to `std::ostream& operator<< <int, 5>(std::ostream&, Array<int, 5> const&)'

问题是您的代码:

friend ostream &operator<<(ostream &out, const Array<ElemType, SIZE> &value);

实际上声明存在一个非模板函数,该函数将成为Array实例的朋友。 稍后,当您在main编写cout << a时,编译器会将<<与此非模板声明进行匹配。 它永远不会达到您稍后提供的operator<<的主体,因此永远不会实例化该主体的副本,因此会产生未定义的引用错误。

解决此问题的一种方法是显式实例化主体。 但这很la脚,因为您必须为代码中发生的每个Array实例化编写一个显式实例化。 所以我们不会这样做。

最简单的解决方案是将operator<<的正文放在类定义中。

另一个选择是声明operator<<是模板函数。

Trevor Hickey的代码显示了执行此操作的一种方法,尽管这样做的缺点是Array<C, D>::operator<<可以访问Array<A, B>::elements

一种更安全的方法是在类之前声明operator<<

template<typename ElemType, int SIZE>
class Array;

template<typename ElemType, int SIZE>
ostream &operator<<(ostream &out, const Array<ElemType, SIZE> &value);

然后再执行其余的代码。 现在,该类中的friend声明将匹配先前存在的模板,而不是声明一个新的非模板。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM