2014-01-15 6 views
5

I по существу есть макет версию std::integral_constant, которая включает в себя переменную, и я хочу, чтобы специализировать шаблон функции для этих классов, производных от Base<T>, как это:Специализируется шаблон функции для шаблонного производного класса

template<class T> struct Base{ 
    typedef T type; 
    T t; 
}; 

template<class T> struct A : Base<T>{ 
    static constexpr T value = 1; 
}; 
template<class T> struct B : Base<T>{ 
    static constexpr T value = 2; 
}; 

struct Unrelated{}; 

// etc. 

template<class T> void foo(T t){ 
    //I would like to specialize foo for A and B and have a version for other types 
} 


int main(){ 
    foo(A<float>());//do something special based on value fields of A and B 
    foo(B<float>()); 
    foo(Unrelated()); //do some default behavior 
} 

Вот Основные вопросы:

  • я не могу включить value в качестве шаблона, как я ожидал T = double, float, или некоторые другие нецелых типов (в противном случае я бы просто продлить std::integral_constant)
  • я не могу чисто использовать std::is_base, как я должен был бы сделать std::is_base<Base<T::type>,T>
  • Ведение foo(Base<T>&) не позволил бы мне видеть value, и я не хочу, чтобы прибегать к виртуальной value() функции (или отражения).
  • И, очевидно, я бы хотел избежать специализации foo для каждого производного класса.

Я думаю, что ответ заключается в использовании is_base, но я не смог заставить его работать независимо от того, как я пытался его использовать. Есть ли более простой способ, которым я не хватает?

+0

Конечно, у вас есть опечатка или два. 'template struct A: Base {' должен быть 'template struct A: Base {'. Это твоя проблема? –

+0

+1 для четкого выражения первого * того, что вы пытаетесь сделать, а затем * как * вы пытаетесь это сделать и, наконец, спрашиваете *, как вы должны делать то, что вы пытаетесь сделать. –

+0

Кроме того, прочитайте [это] (http://www.gotw.ca/publications/mill17.htm) –

ответ

1

должно работать:

template<typename,typename = void> 
struct IsBase 
    : std::false_type {}; 

template<typename T> 
struct IsBase<T, typename std::enable_if< 
        std::is_base_of<Base<typename T::type>,T>::value 
       >::type> 
    : std::true_type {}; 

template<class T> 
typename std::enable_if<IsBase<T>::value>::type foo(T t){ 
    // use T::value 
} 

template<class T> 
typename std::enable_if<!IsBase<T>::value>::type foo(T t){ 
    // general case 
} 

Live example

+0

Не работает, если я делаю 'foo ()' (для меня, по крайней мере, на g ++ 4.6), хотя у него нет проблемы с ошибкой в ​​'typename T :: type.' Как я уже сказал, я сделал практически то же самое, но не смогли заставить его полностью работать, как хотелось бы. – user783920

+1

@ user783920 'foo ()' не предоставляет параметр, но 'foo' (как вы его определили) требует параметра' t'. Я не думаю, что смогу помочь, если вы не представите правильное описание своей проблемы. –

+0

Я удалил шаблон, но теперь он работает. Наверное, я забыл сэкономить или что-то, извините. – user783920

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