专用于Base和所有Derived的类

时间:2014-06-03 23:20:42

标签: c++ templates template-specialization

我有一个Base-class和一个派生类。我想设计一个C类,当基类或派生对象被移交时,它会以不同的方式作出反应:

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

template<typename T>
class C
{
public:
    static int f(T&& arg) {return 1;};
};
// Specialize C, not the function
template<typename T>
class C<T>
{
public:
    static int f(T&& arg) {return 2;};
};

template<typename T>
int function(T&& arg) {
    return C<T>::f(std::forward<T>(arg));
}

int main()
{
    std::cout << function(1) << std::endl;
    std::cout << function(Base<float>()) << std::endl;
    std::cout << function(Derived()) << std::endl;
}

这应该打印:

  

1

     

2

     

2

有没有办法可以通过专门使用类C而不是函数来实现这一点。实际上我只是交出C型,一切都发生在我无法触及的范围内。 为了清楚起见,功能的实​​现可能看起来像那样但我无法说清楚。我所知道的只是f:int f(T&&)的签名;而且我必须拥有一个具有该签名功能的C类。

1 个答案:

答案 0 :(得分:2)

通过功能()的专业化:

示例代码优先:

template< class T >
struct Base
{};

struct Child : Base<int>
{    };

template<typename T>
class C1
{
public:
    static int f(T&& arg) {return 1;}
};

template<typename T>
class C2
{
public:
    static int f(T&& arg) {return 2;}
};

template<typename T>
typename std::enable_if< std::is_base_of<Base<int>, T>::value, int >::type function(T&& arg) 
{
    return C2<T>::f(std::forward<T>(arg));
}

template<typename T>
typename std::enable_if< !std::is_base_of<Base<int>, T >::value, int >::type function(T&& arg) 
{
    return C1<T>::f(std::forward<T>(arg));
}

int main()
{
    std::cout << function(1) << std::endl;
    std::cout << function(Base<int>()) << std::endl;
    std::cout << function(Child()) << std::endl;
    return 0;
}

为什么:

所以这里的分歧就是我写了两个版本的function()。函数()的返回类型看起来有点毛茸茸,但如果T具有Base&lt;的话,将编译第一个版本。 int&gt;作为基本类型。否则将使用第二个版本。

的std :: enable_if&LT;&GT;是一个很好的工具,如果不满足条件,会导致模板扩展失败。在这种情况下,如果T没有Base&lt;则导致模板扩展失败。 int&gt;作为基类。在模板扩展失败的情况下,编译器继续寻找将编译的另一个版本的function()。

C1和C2是两个不同的对象,如果T将Base作为子节点,则使用C2,否则使用C1。

通过C的专业化:

template< class BaseArgument >
Base< BaseArgument > get_Base_type_of( Base< BaseArgument >&& );

template< class T >
struct has_Base
{
  typedef char yes;
  typedef long no;

  template< typename T1 >
  static yes Check( decltype( get_Base_type_of( declval<T1>() ) )* );

  template< typename T1 >
  static no Check( ... );

  static const bool value = sizeof( decltype( Check<T>(0) ) ) == sizeof( yes ) ;
};

template< typename T, typename Placeholder = void >
class C
{
public:
    static int f(T&& arg) {return 1;};
};

template<typename T>
class C< T, typename std::enable_if< has_Base<T>::value >::type >
{
public:
    static int f(T&& arg) {return 2;};
};
相关问题