如何在模板typename上编译时条件?

时间:2017-06-19 12:57:16

标签: c++ templates typetraits

假设我有一个class A模板,如下所示:

template<typename T>
class A
{
    T data;
public:
    void func(){} //concerned function ** see here **
};

现在我有另一个class B模板,比如

template<typename U>
class B
{
    // ... something whatever
};

这意味着不构建函数的条件是直接模板typename TBC可以是任何类型,包括AB

2 个答案:

答案 0 :(得分:2)

  1. 除非使用了odr,否则不会生成类模板的成员函数。这是机制力量的一部分。

  2. 如果您想限制使用此成员函数,那么您确实会使用std::is_same。诀窍是定义适当的特征/元函数:

    template<class, template<class...> class>
    struct is_template_instance : std::false_type {};
    
    template<template<class...> class T, class... Cs>
    struct is_template_instance<T<Cs...>, T> : std::true_type {};
    

    真正的专业化只会选择is_template_instance<std::vector<int>, std::vector>之类的东西。现在只需使用静态断言或std::enable_if

    auto func() ->
      typename std::enable_if<!is_template_instance<T, B>::value>::type {
    }
    

答案 1 :(得分:1)

您需要partial specialize模板:

template<typename C>
class A<B<C>> // Used when A<B<C>> is instantiated
{
    B<C> data;
};

唯一的缺点是这需要一些代码重复,这并非总是可行。

相反,您可以创建一个具有所有功能的基类,并从该基础派生:

// Base class with all the common functionality.
template<typename T>
class A_impl
{
protected:
    T data;
};

// Special case when 'func' is available.
template<typename T>
class A : public A_impl<T>
{
public:
    void func() {}
};

// Another special case where 'func' is not available.
template<typename C>
class A<B<C>> : public A_impl<B<C>> {
};