模板函数,它接受所有派生类型的类型和对象的对象

时间:2016-01-21 21:53:01

标签: c++ c++14 template-meta-programming

我想要一个模板函数,它从Base获取Base的所有对象或任何派生类(这里只有一个派生类)。我的以下示例不起作用,请参阅有关出现的内容和我想要实现的内容的评论:

#include <iostream>

template <typename T>
class Base { };

template< typename T>
class Derived: public Base<T> { };

//FIRST
template < typename T>
void Do( const T& )
{
    std::cout << "FIRST " << __PRETTY_FUNCTION__ << std::endl;
}

// SECOND Should eat all types which derives from Base<T>
template < typename T>
void Do( Base<T>& base)
{
    std::cout << "SECOND " << __PRETTY_FUNCTION__ << std::endl;
}


int main()
{
    Derived<int> derived;
    Base<int> base;

    Do(base);       // SECOND void Do(Base<T>&) [with T = int]           OK
    Do(derived);    // FIRST void Do(const T&) [with T = Derived<int>]   Fail -> should go to SECOND!
    Do(1);          // FIRST void Do(const T&) [with T = int]            OK
}

原始代码有Base作为模板类。我简化了这一点,但应该记住。

我虽然关于基本和派生类型的enable_if禁用FIRST函数,但我找不到正确技巧的想法。并且只为基础和派生类启用SECOND一个是一个选项,但我不能在这里得到诀窍。

我看到了enable_if type is not of a certain template class,但这对派生的内容没有帮助。

编辑: 对不起,我给出的例子很简单。正如标题中给出的,我需要一些模板内容来确定模板函数的类型是模板的实例还是从该模板类型派生的。我修改了示例代码。

1 个答案:

答案 0 :(得分:2)

写一个特征来检查从Base的任何专业化派生的类:

namespace detail {
    template<class T>
    std::true_type test(Base<T>*);
    std::false_type test(...);
}

template<class T>
struct is_derived_from_Base : decltype(detail::test((T*)nullptr)) {};

并使用它来约束第一个函数模板:

template < typename T, typename = std::enable_if_t<!is_derived_from_Base<T>{}> >
void Do( const T& )
{   
    std::cout << "FIRST " << __PRETTY_FUNCTION__ << std::endl;
}