Почему я не могу использовать защищенный вложенный класс в качестве параметра шаблона для другого вложенного защищенного класса?

Узнав о том, что вложенные классы являются членами класса вложенности и, следовательно, имеют полный доступ к членам класса вложенности (по крайней мере, для 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).
Так что да, это довольно косметический проблема, чтобы иметь — но я считаю, что это показывает, что я не понимаю, что происходит, и, следовательно, мне любопытно узнать о но почему?.

2

Решение

Вы можете свести свой пример к простому:

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.

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]