Специализация метода шаблона класса для производных классов - PullRequest
0 голосов
/ 23 февраля 2012

Буду признателен за помощь в специализации метода doIt() в следующем фрагменте кода для классов, имеющих общий базовый класс, как показано ниже

#include <iostream>
#include <boost/utility.hpp>
#include <boost/type_traits.hpp>

struct BarBase {};
struct Bar: BarBase {};

struct FooBase {};
struct Foo: FooBase {};

template <typename T>
struct Task
{
    // I'd like to specialize this method for classes with a common base class
    void doIt();        
};

// my attempt (does not compile)
template <typename T>
typename boost::enable_if<boost::is_base_of<FooBase, T> >::value
doIt() {
    std::cout << "Type is derived from FooBase\n";
}


int main()
{
    Task<Foo> f;
    f.doIt();
}

Ответы [ 2 ]

1 голос
/ 23 февраля 2012

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

Что вы также можетеdo имеет функцию-член шаблона в классе шаблона и специализируется на этом.Таким образом, вы можете сделать это:

template <typename T>
struct Task
{
    void doIt() { doItPriv<T>(); }
private:
    template<typename T1>
    void doItPriv();  
};

, а затем специализироваться doItPriv.

0 голосов
/ 23 февраля 2012

Согласно этому ответу ,

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

Вот почему вы не можете сделать что-то подобное:

template <typename T>
struct Task
{
    typename std::enable_if<std::is_base_of<FooBase, T>::value>::type doIt() {
        std::cout << "Type is derived from FooBase\n";
    }   

    typename std::enable_if<std::is_base_of<FooBase, T>::value == false>::type doIt()
    {
    }
};

Здесь doIt() не шаблон, поэтому никаких вычетов.Но вы можете сделать следующее:

template <typename T1>
struct Task
{
    template <typename T>
    typename std::enable_if<std::is_base_of<FooBase, T>::value>::type doIt_() {
        std::cout << "Type is derived from FooBase\n";
    }   

    template <typename T>
    typename std::enable_if<std::is_base_of<FooBase, T>::value == false>::type doIt_()
    {
    }

    void doIt()
    {
        doIt_<T1>();
    }
};
...