2011-12-22 3 views
2

Я понимаю, как создавать черты типа, а затем специализироваться на определенный класс, но в моем случае я хотел бы специализироваться на шаблоне класса. Код ниже не компилируется, но идея состоит в том, что специализация Traits для MyTemplatisedClass должна работать, для которой когда-либо используется пользователь, который решает использовать с MyTemplatisedType.Определение черт для шаблонных классов

class Traits 
{ 
public: 
    static bool someProperty(void) { return false; } 
}; 

template<typename Type> 
class MyTemplatisedClass 
{ 
}; 

template<typename Type> 
template<> 
class Traits< MyTemplatisedClass<Type> > 
{ 
public: 
    static bool someProperty(void) { return true; } 
}; 

int main(int argc, char* argv[]) 
{ 
    std::cout << Traits< MyTemplatisedClass<float> >::someProperty() <<std::endl; //This should be true 
    return 0; 
} 

Возможно ли это, или я прошу слишком много? Согласно компилятору первой проблемой является

error C2989: 'Traits' : class template has already been declared as a non-class template  

Это правильно, но как я могу это исправить? Если это имеет какое-то значение, мне не нужно, чтобы он работал на нетемплифицированных классах, просто шаблонизированные были в порядке. Редактировать: На самом деле было бы неплохо, если бы оно работало как для templatised, так и для non tem tematatised классов.

ответ

2

Traits должен быть шаблоном для специализации.

В специализации отбросить строку с пустым <>: это не шаблон, вложенный в шаблон или что-то в этом роде.

template <typename Type> //can only specialize templates 
class Traits 
{ 
public: 
    static bool someProperty(void) { return false; } 
}; 

template<typename Type> 
class MyTemplatisedClass 
{ 
}; 

template<typename Type> 
//template<> //Too much here 
class Traits< MyTemplatisedClass<Type> > 
{ 
public: 
    static bool someProperty(void) { return true; } 
}; 

Но если вы имели в виду специализации для любой шаблон с одним аргументом типа, то это было бы:

template < template <class> class SomeTemplatizedType, class Type> 
//   ^^^^^^^^^^^^^^^^^^^^^^ 
//   names a template, not type 
class Traits< SomeTemplatizedType<Type> >; 
//   ^^^^^^^^^^^^^^^^^^^ ^
//    template name  | 
//        argument 
+0

Спасибо, ребята, вы все дали правильный ответ, но я могу только принять его. Я собираюсь пойти с UncleBens за дополнительной информацией. – PolyVox

+0

@UncleBens: Могли бы вы представить примеры для обоих случаев. Я не совсем понимаю, в чем разница или что вы подразумеваете, специализируясь на «любом» шаблоне с одним аргументом. – Sarien

1

Начальный класс должен быть «базовый случай», т. е. шаблоны для принятия аргументов любого типа. Затем вы можете беспокоиться о том, какие другие специализации вы хотите вызвать.

template<typename T> class Traits 
{ 
public: 
    static bool someProperty(void) { return false; } 
}; 

template<typename Type> 
class MyTemplatisedClass 
{ 
}; 

template<typename Type> class Traits< MyTemplatisedClass<Type> > 
{ 
public: 
    static bool someProperty(void) { return true; } 
}; 

Для того, чтобы на самом деле использование это время компиляции вычислений, вам нужно будет сделать его неотъемлемой константа обледеневших. Функция не может быть constexpr, даже если тривиально ее значение известно во время компиляции. Как она стоит, я не могу сделать, например,

template<typename T> std::enable_if<Traits<T>::value, sometype> somefunc(); 
+0

Спасибо, ребята, вы все дали правильный ответ, но я могу только принять его. Я собираюсь пойти с UncleBens за дополнительной информацией. – PolyVox

1

Проблема заключается в том, что вы объявили Traits как класс, а не шаблона класса. Просто добавьте template<typename> к определению Traits и удалите ложный template<> со специализацией, и все должно быть хорошо.

template<typename>    // <--- Add this 
class Traits 
{ 
public: 
    static bool someProperty(void) { return false; } 
}; 

template<typename Type> 
class MyTemplatisedClass 
{ 
}; 

template<typename Type> 
// template<>     // <--- Remove this 
class Traits< MyTemplatisedClass<Type> > 
{ 
public: 
    static bool someProperty(void) { return true; } 
}; 

int main(int argc, char* argv[]) 
{ 
    std::cout << Traits< MyTemplatisedClass<float> >::someProperty() <<std::endl; //This should be true 
    return 0; 
} 
+0

Спасибо, ребята, вы все дали правильный ответ, но я могу только принять его. Я собираюсь пойти с UncleBens за дополнительной информацией. – PolyVox

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