Действительна ли эта явная специализация функции шаблона шаблона элемента шаблона элемента шаблона класса?

Кто-нибудь знает, действительна ли эта явная специализация:

template <class>
struct L {
  template <typename T>
  struct O {
    template <typename U>
    static void Fun(U);
  };
};

template<>
template<typename T>
template<typename U>
void L<int>::O<T>::Fun(U) {}

clang trunk (12/3/2013) дает следующую ошибку:
f: ... \ test.cpp: 36: 20: error: вне очереди определение Fun из класса O без определения

void L<int>::O<T>::Fun(U) {}
     ~~~~~~~~~~~~~~^

Произошла 1 ошибка.

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

Примечание: я несколько удивлен, что это ошибка - я ожидал, что специализация будет выбрана для любого семейства аргументов шаблона, с которым создается экземпляр Fun, начиная с <int><?any><?any>.

Это ошибка с лязгом или ошибка в моих ожиданиях?

Спасибо!

====== РЕДАКТИРОВАТЬ (думаю, у меня есть ответ) ========

Хорошо - я думаю, что нашел подтверждающую формулировку - из N3797 (рабочий проект после Чикаго 2013) - 14.7.3 / 16 =>

"В явном объявлении специализации для члена шаблона класса или шаблона члена, который появляется в области пространства имен, шаблон члена и некоторые из включающих его шаблонов классов могут оставаться неспециализированными, за исключением того, что объявление не должно явно специализировать шаблон члена класса, если шаблоны включающих его классов также явно не специализируются ".

Если я правильно интерпретирую, нам нужна явная специализация O, если мы собираемся объявить явную специализацию его члена? Отсюда ошибка.

Верный?

Спасибо!


person Faisal Vali    schedule 03.12.2013    source источник
comment
Я не думаю, что цитируемый вами текст имеет отношение к делу; это говорит о том, что вы не можете специализироваться L<X>::O<int>. В отличие от L<int>::O<T>, что нормально.   -  person M.M    schedule 07.06.2018
comment
Добавлен тег language-lawyer, поскольку я хотел бы увидеть, где в Стандарте требуется, чтобы вам нужно было переопределить L<int>::O, прежде чем эта специализация будет разрешена   -  person M.M    schedule 07.06.2018


Ответы (1)


Я не верю, что это действительно так. Я недостаточно разбираюсь в языке, чтобы рассказать вам, как / если вы можете сделать это, не предоставляя специализацию верхнего уровня, как показано ниже, или есть ли ярлык для пропуска шаблонов репликации, но сообщение об ошибке довольно четкое: Вы пытаетесь предоставить реализацию статического члена зависимого вложенного типа, не предоставляя специализации фактической зависимости. Т.е. это работает:

#include <iostream>

template <typename>
struct L
{
    template <typename T>
    struct O
    {
        template <typename U>
        static void Fun(U)
        {
            std::cout << "General: " << __PRETTY_FUNCTION__ << std::endl;
        };
    };
};

// provide specialized L
template<>
struct L<int>
{
    template <typename T>
    struct O
    {
        template <typename U>
        static void Fun(U);
    };
};

// L<int> is a specialized type, so provide the rest.
template<typename T>
template<typename U>
void L<int>::O<T>::Fun(U)
{
    std::cout << "Special: " << __PRETTY_FUNCTION__ << std::endl;
}


int main()
{
    L<int>::O<double> nobj;
    nobj.Fun(10);

    L<double>::O<int> nobj2;
    nobj2.Fun(20);

    return 0;
}

Вывод

Special: static void L<int>::O<double>::Fun(U) [T = double, U = int]
General: static void L<double>::O<int>::Fun(U) [T = int, U = int]
person WhozCraig    schedule 04.12.2013
comment
Я действительно думаю, что вам просто нужно предоставить: `template‹ ›template‹ class T ›struct L ‹int› :: O {template‹ class U ›static void Fun (U); }; - но я все еще не уверен, зачем это нужно? - person Faisal Vali; 04.12.2013
comment
Вы правы, и с этим вы можете использовать декларацию для функции, которую вы указали ранее. Если у меня будет возможность (хаос @ home), я обновлю это. - person WhozCraig; 04.12.2013