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

defining a member C++ class template in namespace context with a template parameter that is private in the class containing the template declaration

提问人:radio32145 提问时间:10/18/2023 最后编辑:user12002570radio32145 更新时间:10/19/2023 访问量:109

问:

我想在命名空间上下文中定义一个成员 C++ 类模板。成员类模板和该模板的参数使用的类型在包含成员模板的类中声明为私有。编译器会抱怨,因为模板参数的类型被声明为私有。

当我使用 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

请注意,在编译的私有范围内定义就可以了struct Nclass A

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

因此,问题在于编译器的行为似乎不一致:当在 的作用域中定义时,允许将其用作模板参数,但在命名空间作用域中定义时不允许使用。为什么不呢?struct A::Sstruct N*struct A::Sclass A

C++ GCC 类模板

评论

0赞 n. m. could be an AI 10/18/2023
struct S { ==> struct A::S {
0赞 user12002570 10/18/2023
你为什么在课堂上同时使用两者?您需要按照此答案中的说明进行限定,并删除说明符。publicprivateASprivate
0赞 user12002570 10/19/2023
这似乎是一个 gcc 错误如此处所述。

答:

1赞 Thomas 10/18/2023 #1

在您提供的代码中,您声明了一个名为 outside 的新结构。要表明您是在其中定义私有结构而不是新结构,您需要更改为(注意要添加的)。SAAtemplate<const A::N* K> struct S {};template<const A::N* K> struct A::S {};A::

0赞 Haiyu Zhu 10/18/2023 #2

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

在文件中(公共标头)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();
}
0赞 user12002570 10/18/2023 #3

首先,在外部定义结构时,您没有使用封闭类对其进行限定。要解决此问题,只需添加以使用封闭类进行限定即可。SA::S


这似乎是一个 gcc 错误。clang 和 msvc 都接受该程序。

GCC 拒绝内部私有类模板的类外定义

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 

评论

0赞 radio32145 10/19/2023
我编辑了我的问题以解决您注意到的第一个问题。我问题的重点是,我不想声明和作为 .struct Nstruct Sclass A
0赞 user12002570 10/19/2023
@radio32145 这似乎是一个 gcc 错误。请参阅更新后的答案。