2010-09-24 2 views
3

я не понимаю, почему в следующем коде, я позволил создать функцию print_private_template в то время как компилятор жалуется print_private_class:Частные классы шаблонов/Структура видимость

#include <cstdio> 

class A 
{ 
    private: 
     template <unsigned T> 
     struct B 
     { 

     }; 

     struct C 
     { 

     }; 

    public: 
     template <unsigned T> 
     B<T> getAb() 
     { 
      return B<T>(); 
     } 

     C getAc() 
     { 
      return C(); 
     } 
}; 

template<unsigned T> 
void print_private_template(const A::B<T> &ab) 
{ 
    printf("%d\n", T); 
} 

void print_private_class(const A::C &ac) 
{ 
    printf("something\n"); 
} 

int main(int, char**) 
{ 
    A a; 

    print_private_template(a.getAb<42>()); 

    print_private_class(a.getAc()); 

    return 0; 
} 

Является ли это ожидаемое поведение? ошибка/расширение компилятора?

Просто чтобы быть ясно, моя цель состоит в том, чтобы сделать ошибку компилятора на как использование print_private_template и print_private_class.

+0

оба они вызывают ошибку компилятора в MSVC2008 – YeenFei

ответ

2

Comeau действительно дает ошибку (если вы закомментировать print_private_class функции и ее вызов в строгом режиме C++ 03.

ComeauTest.c(31): error: class template "A::B" (declared at line 7) is inaccessible void print_private_template(const A::B &ab) ^ detected during instantiation of "print_private_template" based on template argument <42U> at line 45

G ++ 4.5 на Windows, не сообщает об ошибке с -std=c++ -Wall -pedantic хотя.

Ваш класс A::C и шаблонный класс A::B<T> оба имеют один и тот же видимость, как все нормальные членов. Таким образом, как и print_private_classprint_private_template требуют диагностики.

11.8 Nested classes [class.access.nest]

1 A nested class is a member and as such has the same access rights as any other member. The members of an enclosing class have no special access to members of a nested class; the usual access rules (Clause 11) shall be obeyed.

+0

Я так понял, что я обнаружил ошибку компилятора в GCC? – LiraNuna

+0

IIRC, GCC 4.5 (тот, который я использую) является экспериментальной сборкой. Должны быть некоторые проблемы с качеством реализации. Но, конечно же, вы можете продолжить и подать это. – dirkgently

+0

Я использую GCC 4.4.3, поэтому я сомневаюсь, что проблема исходит из вашей неустойчивой сборки. – LiraNuna

0

Как указано Dirk Gently, GCC не выполняет контроль доступа при создании шаблонных структур/классов, вложенных в другие (шаблонные) структуры/классы.

Один из способов обойти это, чтобы инкапсулировать их в нешаблонной структуре:

template<int I> class MyTemplate 
{ 
    struct PT 
    { 
     template<int, typename = void> struct InnerTemplate; 
     // ... specialisations here ... 
    }; 
public: 
    typedef typename PT::template InnerTemplate<I>::SomeType SomeType; 
}; 
typedef MyTemplate<1>::PT::InnerTemplate<1> ThisWontWork; 

Последняя строка не будет компилироваться с ошибкой:

error: 'struct MyTemplate<1>::PT' is private within this context 

я выполню что это некрасиво, особенно нужно использовать PT::template, но, похоже, эффективно препятствует клиентам создавать экземпляры вспомогательных шаблонов, к которым они не предназначены, поэтому стоит сделать снимок.

Смежные вопросы