为什么我不能将受保护的嵌套类用作另一个嵌套受保护类的模板参数?

时间:2013-02-07 21:50:33

标签: c++ templates c++11 nested-class

在了解到嵌套类是嵌套类的成员并因此可以完全访问嵌套类的成员(至少对于C ++ 11,请参阅here)之后,我遇到了一个问题。尝试创建嵌套类模板:

#include <iostream>

using namespace std;

// #define FORWARD 

class A {

// public: // if FooBar is public, the forward declared version works
protected:
  enum class FooBar { // line 11, mentioned in the error message
    foo,
    bar
  };

protected:
#ifdef FORWARD
  // forward declaration only
  template< FooBar fb = FooBar::foo >
  struct B; 
#else
  // declaration and definition inline
  template< FooBar fb = FooBar::foo >
  struct B{
    void print(){ cout << A::i << (fb==FooBar::foo ? " foo" : " not foo") << endl;};
  };
#endif

public:
  B<>* f;
  B<FooBar::bar>* b;
private:
  static const int i = 42;
}; 

#ifdef FORWARD
// definition of forward declared struct
template< A::FooBar fb>
struct A::B{
  void print(){ cout << A::i << (fb==FooBar::foo ? " foo" : " not foo") << endl; };
}; // line 41, mentioned in the error message
#endif


int main(int argc, char **argv)
{
  A a;
  a.f->print();
  a.b->print();
  return 0;
}

这应该(并且确实)输出:

42 foo
42 not foo

问题

如果#define FORWARD未注释,即FORWARD已定义,为什么不编译此代码?

我得到的错误(来自gcc 4.7.2)是

main.cpp:11:14: error: ‘enum A::FooBar’ is protected
main.cpp:41:2: error: within this context

answer到之前的question,我了解到BA的成员,并且应该可以访问其中的(私有)成员(并且它会打印A::i)。那么为什么在课外宣言中不能获得A::FooBar

背景

这显然是其他一些代码的最小示例,其中标题和实现被拆分。我本来希望只转发声明嵌套类模板B,以使类A的接口更具可读性,因为我可以将模板类的实现推送到头文件的末尾(即通过取消评论#define FORWARD得到的行为/设置)。 所以,是的,这是一个相当美容的问题 - 但我相信它表明我不明白发生了什么,因此我很想知道,但为什么呢?

1 个答案:

答案 0 :(得分:5)

您可以将示例简化为:

class A
{
private:
  enum FooBar { foo };

public:
  template< FooBar fb = foo >
  struct B;
};

template< A::FooBar >
struct A::B
{
};

A::B<> a;

这是合法的,由DR 580澄清,并且被Clang ++接受,所以看起来G ++还没有实现该解决方案。

我已将此报告为GCC PR 56248并报告Clang PR 15209,因为Clang也未完全实施DR 580.

相关问题