我有以下代码,该代码尝试为operator
定义和调用输出union
:
#include <iostream>
#include <stdint.h>
template <typename T>
union test
{
using mytype = T;
friend std::ostream& operator<<(std::ostream& stream, test<T> t)
{
stream << static_cast<mytype>(65);
}
};
int main() {
test<int> t;
std::cout << t;
return 0;
}
编译失败,并显示以下错误(实际上是两个错误):
prog.cpp: In function ‘std::ostream& operator<<(std::ostream&, test)’:
prog.cpp:10:28: error: ‘mytype’ does not name a type
stream << static_cast<mytype>(65);
^~~~~~
prog.cpp: In function ‘int main()’:
prog.cpp:15:10: error: non-template type ‘test’ used as a template
test<int> t;
^
如果我将union
替换为struct
,它将正常工作(打印65
)。
如果我用成员函数替换friend
,它也可以工作,但是我必须使用这种friend
语法,因为我想输出operator
。
我还能尝试什么来帮助编译器理解我的代码?
我正在使用gcc 5.3.0;然后,我在gcc 6.3 here的在线版本上进行了尝试,它显示了相同的问题。它永远不会在MS Visual Studio 2017上显示任何编译错误。
答案 0 :(得分:3)
这是GCC错误。该函数是内联定义的,因此名称查找应遵循成员函数的相同规则。
[basic.lookup.unqual]
9名称查找,用于定义朋友的名称 在类授予中内联定义的函数([class.friend]) 友谊应按成员函数中的查找所述进行 定义。如果在类中未定义friend函数 在朋友功能定义中授予友谊,名称查找 应按照在命名空间成员函数中查找所描述的那样进行 定义。
我对GCC 8.2 reproduced your error进行的测试以及您的代码。但是,当class-key
从union
切换到struct
时,它具有no issues,并且如果朋友函数改为成员,它也具有no problem。>
值得注意的是GCC bug 85576,它报告了您遇到的第二个错误,并且毫无疑问是相关的。
答案 1 :(得分:3)
程序格式正确,所以这是一个GCC错误。
除了切换到兼容的编译器之外,您还可以通过使用带有匿名联合成员而不是普通联合的非联合类来解决该错误:
template <typename T>
struct test {
using mytype = T;
friend std::ostream& operator<<(std::ostream& stream, test<T> t)
{
stream << static_cast<mytype>(65);
return stream;
}
union {
// the union members
};
};