gcc 在命名空间上下文中定义一个成员C++类模板,模板参数在包含模板声明的类中是私有的

j9per5c4  于 2023-10-19  发布在  其他
关注(0)|答案(3)|浏览(157)

我想在命名空间上下文中定义一个成员C类模板。成员类模板和该模板的参数使用的类型在包含成员模板的类中声明为私有。编译器会抱怨,因为模板参数的类型被声明为private。
当我使用g
(GCC)13.2.0在文件temp.cc中编译以下代码时,

// the following class definition would go in its own header file
class A {
public: // I don't want to declare struct S public
private:
  struct N;
  template<const N* K> struct S; // I don't want to define struct S here!
};
// the following definition would go in a separate file
template<const A::N* K> struct A::S {
};

我得到以下错误

g++ temp.cc
temp.cc:9:19: error: ‘struct A::N’ is private within this context
    9 | template<const A::N* K> struct A::S {
      |                   ^
temp.cc:5:10: note: declared private here
    5 |   struct N;
      |          ^

有没有一种方法可以安抚编译器 * 而不 * 声明struct N是公共的?
注意,在class A的私有作用域中 * 定义 * struct N可以很好地编译

class A {
public:
private:
  struct N;
  template<const N* K> struct S {}; // no compilation error!
};

因此,问题是编译器的行为似乎不一致:当在class A的作用域中定义struct A::S时,struct A::S可以使用struct N*作为模板参数,但当在namespace作用域中定义时则不行。为什么不呢?

68de4m5k

68de4m5k1#

在你给出的代码中,你在A之外声明了一个名为S的新结构。为了表明您正在A中定义私有结构体而不是新结构体,您需要将template<const A::N* K> struct S {};更改为template<const A::N* K> struct A::S {};(注意添加的A::)。

wbgh16ku

wbgh16ku2#

在另一个文件中定义S,可能会遇到链接错误。我认为您可以使用代理模式,公开API并在内部隐藏数据结构。举个例子,所有的代码都可以是:
A.h文件中(公共头)

class A {
 public:
  Foos();
 private:
  A();
};

A *MakeA();

in A_Proxy.h(内部标题)

include 'A.h'
class AProxy : public A {
private:
  struct N;
  template<const N* K> struct S{}; // decl the S here
};
A *MakeA() {
  return new AProxy();
}
mum43rcc

mum43rcc3#

首先,当在外部定义结构S时,你没有用 * 封闭类 * 来**限定它。要解决这个问题,只需添加A::,使S由封闭类限定。
这似乎是一个gcc bug。clang和msvc都接受这个程序。
GCC rejects out of class definition of inner private class template

class A {
    
        struct N;
        
        template<const N* K> struct S; 
};
// works now

class A::N{};
template<const A::N* K> class  A::S{};//gcc rejects this but clang and msbc accepts this

相关问题