Частные шаблоны классов / структуры видимости - PullRequest
3 голосов
/ 24 сентября 2010

Я не понимаю, почему в следующем коде мне разрешено создавать функцию 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.

Ответы [ 2 ]

2 голосов
/ 24 сентября 2010

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

ComeauTest.c (31): ошибка: шаблон класса "A :: B" (объявлен в строке 7) недоступен void print_private_template (const A :: B & ab) ^ обнаружен во время создания экземпляра "print_private_template" на основе аргумент шаблона <42U> в строке 45

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

Ваш класс A::C и шаблон класса A::B<T> имеют одинаковую видимость с другими обычными членами. Следовательно, и print_private_class, и print_private_template требуют диагностики.

11,8 Вложенные классы [class.access.nest]

1 Вложенный класс является членом и, как таковой, имеет те же права доступа, что и любой другой член. Члены включающий класс не имеет специального доступа к членам вложенного класса; обычные правила доступа (статья 11) будет подчиняться.

0 голосов
/ 26 сентября 2017

Как заявил Дирк Джентли, 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но, похоже, это эффективно предотвращает создание клиентами шаблонов помощников, к которым они не предназначены, поэтому стоит попробовать.

...