1

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

#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; 
} 

Что я делаю неправильно?

Edit: Кстати, ошибка компилятора читает:

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*() 
                         ^

ответ

7

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

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. 
} 

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

+0

спасибо. Быстрый вопрос: если у класса Test были другие функции, есть ли какой-либо чистый способ, который я мог бы наследовать остальную функциональность в Test , а только специализировать эту функцию? Я пытаюсь избежать дублирования большого кода. – Jonathan

+0

@Jonathan Насколько я знаю, не используя только специализированные шаблоны. Возможно, вы могли бы достичь чего-то, смешав наследование. – bolov

+0

@ Джонатан сделал небольшое исследование: вы хотите использовать «Любопытно повторяющийся шаблон шаблона». См. Http://stackoverflow.com/questions/6220337/code-duplication-and-template-specialization-when-specialized-function-has http://stackoverflow.com/questions/2757816/class-template-specializations- с-shared-functional – bolov

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