C++ 要将嵌套类中定义的静态模板函数声明为同级嵌套类中的友元,必须执行哪些操作?

C++ 要将嵌套类中定义的静态模板函数声明为同级嵌套类中的友元,必须执行哪些操作?,c++,templates,friend,nested-class,template-function,C++,Templates,Friend,Nested Class,Template Function,在Linux上使用GCC4.8.2,我想授予工厂方法Create()对类C的私有构造函数的访问权,但在试图声明一个专门的友元时,我得到“error:'Create'未在此范围内声明”。如何在不向B::Create()的所有类型打开声明的情况下使其工作 模板类别A{ 公众: 乙级;; 模板C类; }; 模板 A类::B类{ 公众: 模板静态void Create(); }; 模板 A类::C类{ C()=默认值; 朋友void B::Create(); }; 模板 作废A::B::创建(){ C{

在Linux上使用GCC4.8.2,我想授予工厂方法Create()对类C的私有构造函数的访问权,但在试图声明一个专门的友元时,我得到“error:'Create'未在此范围内声明”。如何在不向B::Create()的所有类型打开声明的情况下使其工作

模板类别A{
公众:
乙级;;
模板C类;
};
模板
A类::B类{
公众:
模板静态void Create();
};
模板
A类::C类{
C()=默认值;
朋友void B::Create();
};
模板
作废A::B::创建(){
C{};
}
int main(){
A::B::Create();
}

我认为您遇到了编译器缺陷。以下代码只使用一层模板,在g++4.8.2中运行良好

class Foo
{
   public:
      template <typename U> static Foo* Create();
};

template <typename U> class Bar : public Foo
{
   private:
      Bar() = default;

      friend Foo* Foo::Create<U>();
};

template <typename U>
Foo* Foo::Create() {
  return new Bar<U>();
}
class-Foo
{
公众:
模板静态Foo*Create();
};
模板类栏:公共Foo
{
私人:
Bar()=默认值;
Foo*Foo::Create();
};
模板
Foo*Foo::Create(){
返回新条();
}
但是,同一个编译器无法编译您的代码。我认为你们已经尝试过的一个解决办法是替换

friend B* B::Create<U>();
friend B*B::Create();

模板
朋友B*B::Create();

我刚刚在MSVC++中测试了你的代码,但也失败了。我可以通过给friend声明一个更明确的名称来修复它。请记住,您可以在任何地方提供完全限定的名称

我刚换了

friend B* B::Create<U>();
friend B*B::Create();

friend B*A::B::Create();

我会启动MinGW,看看它是否真的达到了你期望的效果。

是的,正如你所怀疑的那样,我知道你提出的解决方案确实有效。不幸的是,正如您所知,它提供了从Foo::Create(即对所有U)更广泛地访问Bar的权限。在OP的情况下,我认为我们有一个依赖的基类,这可能会改变一致性解释。请注意,coliru.stacked crook.com的clang++与OP的代码有类似的问题:它抱怨缺少
Create
的定义,这可能是由于友元声明引入了另一个
Create
函数,该函数稍后通过重载解析选择。如果是这样的话,这可能是一个有趣的名称查找问题。在GCC 4.8.2中,我看到更显式的名称出现了相同的错误。好的,在我的MinGW版本(GCC 4.7.1)中,我遇到了与您相同的问题,但相同的代码在MVC++中编译得很好。我会看看我是否能找到解决方法,但现在可能是提交错误报告的时候了。呃,我尝试过的任何东西(除了R Sahu建议的)在Linux上的MinGW 4.7.1或GCC 4.8.2都不起作用。哦,好吧,啊哈!如果我们与
B::Create
的特定专业化成为朋友,例如
朋友void a::B::Create(),它在clang++中工作
在g++4.9.2中,这导致了一个ICE o。OKaslai发现它在MSVC++中工作需要完全的资格认证。好吧,这还不足以使它在g++和clang++中工作。但是,如果我们尝试在友元声明中使用固定的已知类型而不是模板参数
T
(即,我们编写
friend void a::B::Create();
友元void a::B::Create();,它适用于clang++,但g++崩溃(ICE)。
friend void a::B::Create()
使g++5.0的主干顶端因冰而崩溃,所以这至少是一个错误报告。
template <typename V> 
friend B* B::Create<V>();
friend B* B::Create<U>();
friend B* A<T>::B::Create<U>();