2010-07-12 2 views
7

Компиляция кода с помощью G ++ 4.2.1:Неверный частный базовый класс недоступен?

struct S { }; 
template<typename T> struct ST { }; 

template<typename BaseType> 
class ref_count : private BaseType { }; 

template<typename RefCountType> 
class rep_base : public RefCountType { }; 

class wrap_rep : public rep_base<ref_count<S> > { 
    typedef rep_base<ref_count<S> > base_type;  // line 11 
}; 

я получаю:

bug.cpp:1: error: ‘struct S’ is inaccessible 
bug.cpp:11: error: within this context 

Однако, если изменить wrap_rep класс использовать ST:

class wrap_rep : public rep_base<ref_count< ST<int> > > { 
    typedef rep_base<ref_count< ST<int> > > base_type; 
}; 

компилирует нормально , В качестве альтернативы, если я изменю исходный код на:

class wrap_rep : public rep_base<ref_count<S> > { 
    typedef rep_base<ref_count<::S> > base_type; // now using :: 
}; 

он также компилируется в порядке. Для меня исходный код кажется прекрасным как есть. Это ошибка g ++? Если нет, то почему использование шаблона работает? И, для другого случая, почему нужен ::S?

ответ

7

Оба этих кода недействительны (только последний действителен), но ваш компилятор (который не соответствует) только диагностирует один. Как говорится в другом ответе, это использует введенное имя класса. Класс S считается членом-членом S, обозначающим этот же класс. Например (обратите внимание на «класс» ключевое слово, прежде чем S::S в первом примере, необходимо, чтобы заставить ссылку на нагнетаемой имя класса, а не конструктор по умолчанию):

class S { }; 

class S::S object; // creates an S object 
class X : S::S::S::S { }; // derives from class S 

Шаблоны классов также имеют впрыскивается имя класса. Как и введенное имя класса, он наследуется к производным классам, и поэтому ST<int> плохо сформирован, потому что он использует это введенное имя класса, которое, однако, недоступно. Если вы используете GCC менее 4,5, он может иметь что-то делать с change introduced с GCC4.5:

G ++ в настоящее время реализует DR 176. Ранее G ++ не поддерживает использование впрыскиваемого-классовое имя шаблона базового класса как имя типа, и поиск имени нашел объявление шаблона в охватывающей области. Теперь поиск имени находит имя введенного класса, которое может использоваться либо как тип, либо как шаблон, в зависимости от того, следует ли за ним следовать список аргументов шаблона. В результате этого изменения, некоторый код, который ранее был принят, может быть плохо сформирован, потому что

  1. Вводимого-имя-класс не доступно, потому что это из частной базы, или
  2. Вводимых-классовых имя не может использоваться в качестве аргумента для параметра шаблона шаблона.

В любом из этих случаев код можно устранить, добавив спецификатор вложенного имени, чтобы явно указать шаблон. Первый может работать с -fno-access-control; второй отклоняется только с -андатикой.


Чтобы иметь немного больше удовольствия с инжектированных именами классов - обратите внимание, что впрыскивается имя класса не эквивалентно ЬурейеЕ, как можно было бы подумать в первую очередь. Вводимое имя класса является именем класса, но не классифицировано как имя-ЬурейиМ, что означает, что он может быть скрыта функцией, объект или нумератор имена:

// valid, the data-member hides the injected class name 
struct S { int S; }; 

Чтобы обратиться к нагнетаемому имени класса вы можете скажем, class S::S (аналогично, в списке базового класса игнорируются неигровые имена, поэтому вам не нужны специальные предостережения), но простой поиск до S::S будет относиться к элементу данных.

0

Исходный код, скомпилированный в «Sun WorkShop 6 update 2 Compilers C++». Это единственный доступ к моему кабинету. Можете попробовать любой другой компилятор, который у вас есть.

3

Ваш блок S является базовым классом wrap_rep, что означает, что он вводится в wrap_rep, как если бы был анонимный typedef.

Использование оператора :: Перед S в вашем ЬурейеЕ покажет ваш компилятор не использовать S вы унаследовали от, но S в глобальном пространстве имен.

См. this link.

+0

Но тогда почему код работает с базовым классом шаблона? –