专门用于派生类的类模板方法

时间:2012-02-23 12:38:58

标签: c++ templates sfinae

对于共享公共基类的类的以下代码中的方法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 个答案:

答案 0 :(得分:1)

您无法专门化模板类成员。你可以专门化一个类,每个专门化都是一个完整的独立类,它不会从非专用模板中继承任何内容(它可能有也可能没有非专用类的全部或部分成员)。

您还可以做的是在模板类中使用模板成员函数,并将其专门化。所以你可以这样做:

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

然后专门化doItPriv

答案 1 :(得分:0)

根据this回答,

  

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>();
    }
};