Специализация шаблона С++: ошибка компиляции: не является типом

Если я удалю часть специализации шаблона (тот, который пытается напечатать «Тест 2»), код компилируется нормально, но я хотел бы иметь особый случай, который запускает другой путь кода, который выглядит чистым для внешних пользователей. .

#include <iostream>

using namespace std;

struct SpecialType {};

template<typename A , typename B = SpecialType>
class Test
{
public:
    class TestInner
    {
    public:
        TestInner& operator* ();
    };
};

template<typename A , typename B>
typename Test<A , B>::TestInner& Test<A , B>::TestInner::operator* ()
{
    cout << "Test 1" << endl;
    return *this;
}

// If the following is removed, everything compiles/works, but I want this alternate code path:
template<typename A>
typename Test<A , SpecialType>::TestInner& Test<A , SpecialType>::TestInner::operator* ()
{
    cout << "Test 2" << endl;
    return *this;
}

int main()
{
    Test<int , SpecialType>::TestInner test;
    *test;

   return 0;
}

Что я делаю не так?

Изменить: Кстати, ошибка компилятора гласит:

main.cpp:26:44: error: 'Test<A, SpecialType>::TestInner' is not a type
 typename Test<A , SpecialType>::TestInner& Test<A , SpecialType>::TestInner::operator* ()
                                            ^
main.cpp:26:89: error: invalid use of dependent type 'typename Test<A, SpecialType>::TestInner'
 typename Test<A , SpecialType>::TestInner& Test<A , SpecialType>::TestInner::operator* ()
                                                                                         ^

person Jonathan    schedule 11.02.2014    source источник


Ответы (1)


Добавьте объявление для специализированного класса:

template<typename A>
class Test<A, SpecialType>
{
public:
    class TestInner
    {
    public:
        TestInner& operator* ();
    };
};

Проблема в том, что вы определяете член для специализации, которая не объявлена. Специализация шаблонного класса не имеет общих членов или методов с обобщенным шаблоном, поэтому объявление обобщенного шаблона не служит объявлением каких-либо специализаций этого класса шаблона.

Учти это:

template <class T>
class Foo {
  void GeneralFunction(T x);
}

и специализация:

template <>
class Foo<int> {
  void SpecialisedFunction(int x);
}

Здесь Foo</*anything except int*/> имеет только метод GeneralFunction, тогда как Foo<int> имеет только метод SpecialisedFunction.

По той же логике разрешено и это:

template<>
class Foo<float> {
  float GeneralFunction; //here GeneralFunction is a data member, not a method.
}

Короче говоря, вам нужно объявить свою специализацию.

person bolov    schedule 11.02.2014
comment
Спасибо. Быстрый дополнительный вопрос: если бы у класса Test‹A,B› были другие функции, есть ли какой-нибудь чистый способ унаследовать остальную функциональность в Test‹A,SpecialType›, но специализировать только эту одну функцию? Я пытаюсь избежать массового дублирования кода. - person Jonathan; 11.02.2014
comment
@Jonathan Насколько мне известно, не только с использованием специализаций шаблонов. Возможно, вы могли бы чего-то добиться, смешав наследование. - person bolov; 11.02.2014
comment
@Jonathan провел небольшое исследование: вам нужно использовать «Любопытно повторяющийся шаблон шаблона». См. stackoverflow.com/questions/6220337/ stackoverflow.com/questions/2757816/ - person bolov; 11.02.2014
comment
Просто хотел добавить: я наткнулся на этот пост (stackoverflow.com/a/3057522/1917447), который помог мне решить, что Я пытался выполнить. - person Jonathan; 12.02.2014