2014-10-18 4 views
0

У меня есть шаблон шаблона name для обнаружения имен типов. Он работает для простых типов, таких как int, float. Однако для некоторого типа шаблона, такого как std:pair, компилятор (VS2013) сообщает об ошибке в строке, когда я пытаюсь определить ее статическую переменную-член.класс шаблон специализация с шаблоном

#include <cassert> 
#include <memory> 

using namespace std; 

template<class T> struct name{ static const char* value; }; 

template<class T> const char* name<T>::value = "unknown"; 
template<> const char* name<int>::value = "int"; 
template<> const char* name<float>::value = "float"; 
template<class T1, class T2> const char* name<pair<T1, T2> >::value = "pair"; //compilation error 

void main() 
{ 
    assert(name<int>::value == "int"); 
    assert(name<float>::value == "float"); 
    assert(name<double>::value == "unknown"); 
    assert((name<pair<int, char> >::value) == "pair"); 
} 

Если я заменю эту строку следующими четырьмя строками, программа работает должным образом.

template<class T1, class T2> struct name < pair<T1, T2> > { 
    static const char* value; 
}; 
template<class T1, class T2> const char* name<pair<T1, T2> >::value = "pair"; 

Но этот способ выглядит уродливым из-за дублирования кода. Есть ли способ ходить?

Обновлено, чтобы устранить некоторые очевидные стандартные проблемы.

+0

это трудно даже начать перечислять все вещи, которые не так с этим кодом, а сосредоточиться на вопросе под рукой: вы можете только специализироваться статические элементы данных в явном виде, но не частично. –

+0

Мне жаль, что вы используете такой ужасный компилятор, что вы как-то ушли, думая, что ваш код удаленно исправлен. Почти каждая строка имеет серьезную ошибку, и я обвиняю компилятор в том, что вы обманываете вас, думая, что все в порядке. –

+0

Вы должны сделать тип 'static const char * const value' –

ответ

2

Прежде всего: Любая явная специализация должна быть введена template<>. Старайтесь оставаться стандартными.

Но этот способ выглядит уродливым из-за дублирования кода. Есть ли способ ходить?

Нет. Параметр и список аргументов в определении члена, который не является явной специализацией, должны соответствовать спискам первичного шаблона или одной из его частичных специализаций и соответствовать члену шаблона, список которого он Матчи. [Temp.class.spec.mfunc]:

Список параметров шаблона члена шаблона класса частичного специализации должен соответствовать список параметров шаблона класса шаблона частичной специализации. Список аргументов шаблона члена частичной специализации шаблона шаблона должен соответствовать списку аргументов шаблона частичной специализации шаблона шаблона.

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

#define REM_PAR(...) __VA_ARGS__ 
#define PART_SPEC(string, params, ...) \ 
    template<REM_PAR params> struct name <__VA_ARGS__ > \ 
    { static const char* value; }; \ 
    \ 
    template<REM_PAR params> const char* name<__VA_ARGS__>::value = string; 

PART_SPEC("pair", (class T, class U), pair<T,U>) 
2

Прежде всего, для справки, это то, как ваш псевдо-код выглядит в C++:

#include <cassert> // for assert 
#include <cstring> // for std::strcmp 
#include <utility> // for std::pair 

template <class T> struct name 
{ static const char * const value; }; 

template <class T> 
const char * const name<T>::value = "unknown"; 

template <>   // "template <>" for specialization 
const char * const name<int>::value = "int"; 

template <>   // "template <>" for specialization 
const char * const name<float>::value = "float"; 

// template <class T1, class T2>        // Error here (partial 
// const char * const name<std::pair<T1, T2>>::value = "pair"; // spec'n not allowed) 

int main() // return type int 
{ 
    assert(std::strcmp(name<int>::value, "int") == 0);  // strcmp! 
    assert(std::strcmp(name<float>::value,"float") == 0); 
    assert(std::strcmp(name<double>::value, "unknown") == 0); 
    assert(std::strcmp(name<std::pair<int, char>>::value,"pair") == 0); 
} 

Итак, вот как вы можете сделать частичную специализацию work: Специализируйте весь шаблон.

template <class T1, class T2> struct name<std::pair<T1, T2>> 
{ static const char * const value; }; 

template <class T1, class T2> 
const char * const name<std::pair<T1, T2>>::value = "pair"; 
Смежные вопросы