C++17是否允许前向声明嵌套类?

28

不确定在哪里提问(如果这是一个不合适的问题,请随意关闭),但我在C++17提案中没有找到任何关于此特定问题的内容,无论是这个还是这个都没有在处理C++中嵌套命名空间的添加时提及它。

所以目前这是唯一的选择:

class A 
{
public: 
    class B; //forward-declared INSIDE class/namespace
};

class A::B //defined outside
{
};

这在C++17中是否可行?

class A::B; //forward declared NESTED outside of parent class/namespace

class C
{
    A::B *b;
};

然后要么是这个 (1)(似乎是嵌套命名空间定义的提议)

class A::B //definition of A::B without defining A
{

};

或者这个 (2)

class A
{
public:
    class A::B
    {

    };
};

或这个 [3]

class A
{
public:
    class B;
};

class A::B
{
};

我怀疑在定义 A 之前定义 A::B 的定义可能不起作用(尽管建议似乎允许这样做)。


5
classnamespace有很大的不同。但请参见P0289 - cpplearner
2个回答

14

这个问题上有一个提案,标题为Forward declarations of nested classesP0289R0。然而,正如你可以从最后一篇文章"Trip Report: C++ Standards Meeting in Jacksonville, February 2016"中看到的那样,该提案因其他需进一步工作的提案而搁置。我引用了委员会的裁决 (Emphasis Mine):

这将允许像X::A*这样的东西出现在头文件中,而不需要在头文件中也出现X的定义 (前向声明XX::A就足够了)。 EWG 发现了令人信服的用例,因为目前很多类定义只出现在头文件中,因为在头文件中定义的接口使用了类型的嵌套类的指针或引用。 还需要解决一些细节问题。(例如,如果X的定义没有出现在任何其他翻译单位(TU)中会发生什么? 如果X的定义出现在另一个TU中,但没有定义嵌套的class A会发生什么? 如果它确实定义了一个嵌套的类A,但是它是私有的呢? 对于这些问题中的一些或全部,答案可能是“有缺陷的、不需要诊断”,因为诊断这种类型的错误需要显著的链接器支持。)


2
我可能错了,但是提出的问题似乎已经得到了回答。即使它最初被采用为更严格的版本,它也将带来巨大的好处,并且如果后来证明可以放松,那就更好了。我认为更大的问题可能是论文中提到的丢失属性 - 即说X :: A目前自动意味着定义(因此)不会产生任何名称查找。然而,我认为这是可以接受的代价。希望一切都能解决,这个提案能够进入最终的C++17! - Resurrection
@Resurrection 幸运的是或不幸的是,无论这些提出的问题是否得到回答,决定权在于C++委员会 :). 就个人而言,我希望这个提案能够被纳入C++17,因为我认为它很有用,而且总的来说,我认为嵌套类的前向声明是语言中必须填补的漏洞。 - 101010
1
我不明白他们的担忧,难道你使用传统的前向声明时不会遇到完全相同的问题吗?现在你可以前向声明一个不存在的类,或者是在你进行前向声明时没有指定命名空间等。 - ymoreau
4
C++20有什么进展吗?C++20至少是否包含了它? - Kai Petzke
有没有一种方法可以为 P0289R0 投赞成票? - QT-1

1

在我看来,C++语言定义中缺乏类的前向声明能力是一个重大漏洞,这导致人们在应该使用前向引用的地方使用void*,从而存在安全隐患。

以下是一种使用命名空间的解决方法:

  1. 展开需要预先声明的类结构
  2. 使用命名空间分离代码
  3. 使用命名空间进行前向声明
namespace ns1 {
namespace ns2 {  

typedef class C * cptr_t; // declare both class and a pointer type
}}

ns1::ns2::C *cp;      // use forward deceleration of the class
ns1::ns2::cptr_t cp;  // use the typedef

这个解决方法并不能完全解决问题,但在某些情况下可能会有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接