Узнав о том, что вложенные классы являются членами класса вложенности и, следовательно, имеют полный доступ к членам класса вложенности (по крайней мере, для C ++ 11 см. Вот), Я столкнулся с проблемой при попытке создать шаблон вложенного класса:
#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
#endifint 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
Из ответ раньше вопрос я узнал, что B
является членом A
и должен иметь доступ к (частным) членам этого (и это делает, он печатает A::i
). Так почему нет A::FooBar
доступный в объявлении вне класса?
Это, очевидно, минимальный пример для некоторого другого кода, где заголовок и реализация разделены. Я хотел бы только вперед объявить вложенный шаблон класса B
для того, чтобы сделать интерфейс класса A
более читабельным, так как тогда я мог бы отодвинуть реализацию класса шаблона в конец заголовочного файла (то есть поведение / настройку, которые можно получить, не комментируя #define FORWARD
).
Так что да, это довольно косметический проблема, чтобы иметь — но я считаю, что это показывает, что я не понимаю, что происходит, и, следовательно, мне любопытно узнать о но почему?.
Вы можете свести свой пример к простому:
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.
Других решений пока нет …