【问题标题】:How can a template type be restricted to a base class excluding a subclass of this base class?如何将模板类型限制为不包括该基类的子类的基类?
【发布时间】:2019-08-04 09:40:08
【问题描述】:

我有两个课程ABB 派生自 A。现在我尝试在模板中将这些类用于第三类C,模板参数为T。此模板应将T 限制为从A 派生的所有类,不包括BB 的所有子类。我尝试以下方式:

template <typename T = 
    std::enable_if<
        (std::is_base_of<A, T>::value)
        &&(!std::is_base_of<B, T>::value)>::type>
class C {};

这个模板可以编译。但是如果我尝试使用它,例如使用T = int,应用程序也可以编译。所以它也被接受为正确的参数值。应该怎么做才对?

【问题讨论】:

  • 显式传递模板参数时,默认值被忽略,不会出现替换失败。您需要 两个 模板参数才能使其工作。你通过了一个,SFINAE 完成了另一个。

标签: c++ templates sfinae


【解决方案1】:

我觉得用static_assert代替std::enable_if会更清楚,你可以自己指定错误信息。

template <typename T>
class C {
    static_assert(std::is_base_of<A, T>::value && !std::is_base_of<B, T>::value, 
                  "T must be classes derived from A excluding B and all subclasses of B.");
};

LIVE

如果要坚持std::enable_if,则需要保留模板参数T,并使用std::enable_if添加额外的模板参数。请注意,当显式指定模板参数时,默认参数将不会生效(以限制类型)。例如

template <typename T, 
          typename std::enable_if<(std::is_base_of<A, T>::value)
                                   && (!std::is_base_of<B, T>::value)>::type* = nullptr>
class C {
};

LIVE

【讨论】:

    【解决方案2】:

    另一种方式通过模板特化

    template <typename, typename = void>
    class C;
    
    template <typename T>
    class C<T, std::enable_if_t<true == std::is_base_of_v<A, T>
                            && false == std::is_base_of_v<B, T>>>
     { };
    

    这个解决方案也不能被“劫持”解释第二个模板参数

    C<B, void>  cb; // compilation error also explicating the second parameter
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-31
      • 1970-01-01
      • 2013-01-22
      • 2016-02-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多