【问题标题】:Why can't I use a protected nested class as a template parameter for another nested protected class?为什么我不能将受保护的嵌套类用作另一个嵌套受保护类的模板参数?
【发布时间】:2013-01-23 13:48:55
【问题描述】:

在了解嵌套类是嵌套类的成员并因此可以完全访问嵌套类的成员这一事实之后(至少对于 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 我了解到B 是A 的成员,并且应该可以访问它的(私人)成员(确实如此,它会打印A::i) .那么为什么不能在类外声明中访问A::FooBar 呢?

背景

这显然是一些头和实现分离的其他代码的最小示例。我希望只转发声明嵌套类模板B 以使A 类的接口更具可读性,因为那时我可以将模板类的实现推到头文件的末尾(即行为/setup 可以通过取消注释#define FORWARD 来获得)。 所以是的,这是一个相当化妆品的问题——但我相信这表明我不明白发生了什么,因此我很想了解,但为什么呢? .

【问题讨论】:

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


    【解决方案1】:

    您可以将示例简化为:

    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。

    【讨论】:

    • 好吧,我想我根本不擅长查看编译器以引入错误;)感谢您向我展示了一个更好(又名更小)的示例代码——我需要获得的另一项技能。
    猜你喜欢
    • 1970-01-01
    • 2022-11-16
    • 2013-03-31
    • 2012-08-19
    • 1970-01-01
    • 2015-07-16
    • 2012-09-05
    • 2016-03-11
    • 1970-01-01
    相关资源
    最近更新 更多