联合的朋友函数中出现错误“ ...未命名类型”-为什么?如何解决?

时间:2019-01-31 16:11:24

标签: c++ templates g++ unions

我有以下代码,该代码尝试为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上显示任何编译错误。

2 个答案:

答案 0 :(得分:3)

这是GCC错误。该函数是内联定义的,因此名称查找应遵循成员函数的相同规则。

  

[basic.lookup.unqual]

     

9名称查找,用于定义朋友的名称   在类授予中内联定义的函数([class.friend])   友谊应按成员函数中的查找所述进行   定义。如果在类中未定义friend函数   在朋友功能定义中授予友谊,名称查找   应按照在命名空间成员函数中查找所描述的那样进行   定义。

我对GCC 8.2 reproduced your error进行的测试以及您的代码。但是,当class-keyunion切换到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
    };
};