c++ Friend函数在msvc中工作,但gcc和clang拒绝代码

pqwbnv8z  于 11个月前  发布在  其他
关注(0)|答案(1)|浏览(100)

我正在使用朋友函数,但面临一个问题,似乎可以用MSVC编译,但不能用gcc和clang编译。下面是一个简化的例子来展示这个问题:

#include <iostream>
template<typename T>
class Outer
{
     struct Inner;
     friend void foo(); 
};

template<typename T>
struct Outer<T>::Inner
{
  template<typename S> friend void bar(typename Outer<S>::Inner);    
};
template<typename S> void bar(typename Outer<int>::Inner) //but this private access works in msvc but not in gcc and clang?  
{ 
   //typename Outer<int>::Inner k;   //doesn't work as expected in all compilers(including msvc) 
   std::cout << "bar called";
}
void foo()
{
    std::cout << "foo called";
    Outer<int>::Inner i;
    bar<int>(i);    
}
int main()
{
    Outer<int> outer;
    foo();
}

字符串
Demo
上面的程序可以在msvc下工作,但不能在gcc和clang下工作。Gcc的代码是error: struct Outer<int>::Inner is private within this context。正确的行为是什么?

还有一种方法可以让程序与所有编译器一起工作吗?

2cmtqfgy

2cmtqfgy1#

MSVC在这里似乎是错误的,因为Outer<T>::InnerOuter<T>的私有成员。
有没有一种方法可以让程序在所有编译器上都能工作?
是的,您可以在Outer中添加一个 *friend template声明 *,这样函数模板bar也是Outer的friend,如下所示。

方法一

这里我们在barOuter中添加一个friend模板声明。

#include <iostream>
template<typename T>
class Outer
{
     struct Inner;
     friend void foo(); 
     //added this friend template declaration
     template<typename S> friend void bar(typename Outer<S>::Inner);  
};

template<typename T>
struct Outer<T>::Inner
{
  template<typename S> friend void bar(typename Outer<S>::Inner);     
};
//-------------------------------------------v-------------->changed this int to S
template<typename S> void bar(typename Outer<S>::Inner) //works now in all compilers  
{ 
     
   std::cout << "bar called";
}
void foo()
{
    std::cout << "foo called";
    Outer<int>::Inner i;
    bar<int>(i);    
}
int main()
{
    Outer<int> outer;
    foo();
}

字符串
Working demo
请注意,在这种特殊情况下,您可以省略Inner中的完整friend模板声明,因为您实际上并没有从foo访问Inner的任何私有内容。Demo

相关问题