c++ - 指定类模板参数的要求

标签 c++ templates c++17 template-specialization

我有几个类似这样的类(class):

struct neg_inf {
    constexpr double operator()() { return -std::numeric_limits<double>::infinity(); }
};

struct pos_inf {
    constexpr double operator()() { return std::numeric_limits<double>::infinity(); }
};

template<typename dX, class LowerBound, class UpperBound>
class limit {
    dX dx;
    UpperBound upperBound;
    LowerBound lowerBound;
    double step_size;

    limit( dX x, LowerBound lower, UpperBound upper, double step = 1 ) :
        dx{ x }, lowerBound{ lower }, upperBound{ upper }, step_size{ step }
    {}

    dX value() const { return dx; }
    LowerBound lower() const { return lowerBound; }
    UpperBound upper() const { return upperBound; }
    double step() const { return step_size; }            
};

到目前为止,这些类都按预期工作。现在我想使用 std::enable_if_tstd::is_arithemtic std::is_same 等条件来修改模板参数。

这些是实例化限制对象需要满足的条件。

  • dX must be at least arithmetic and numerical
  • Lower & Upper bound must be either numerical, arithmetic or neg_inf or pos_inf.

例如,这些是有效的实例化:

dX = 1st and can be any: int, long, float, double, /*complex*/, etc.

limit< 1st, 1st, 1st >     // default template

limit< 1st, 1st, pos_inf >  // these will be specializations
limit< 1st, 1st, neg_inf >
limit< 1st, pos_inf, 1st >
limit< 1st, neg_inf, 1st >
limit< 1st, pos_inf, pos_inf >
limit< 1st, neg_inf, neg_inf >
limit< 1st, neg_inf, pos_inf >
limit< 1st, pos_inf, neg_inf >

这些是实例化我的模板的有效条件。当 UpperBound 和/或 LowerBoundinfinity 类型时,我计划部分专门化此类。当上限下限是数值算术类型时,通用或默认模板将处理它们。

我的问题是,使用 type_traits 库,我的类的模板声明会是什么样子?

最佳答案

将模板类型限制为类的一种方法是为 SFINAE 添加额外的参数:

template <typename dX, class LowerBound, class UpperBound, typename Enabler = void>
class limit;

然后,通过适当的 SFINAE 提供特化

template <typename dX, class LowerBound, class UpperBound>
class limit<dX,
            LowerBound,
            UpperBound,
            std::enable_if_t<my_condition<dX, LowerBound, UpperBound>::value>>
{
    // ...
};

因此,在您的情况下,my_condition 应该类似于

template <typename dX, class LowerBound, class UpperBound>
using my_condition =
    std::conjunction<std::is_arithmetic<dX>,
                     std::disjunction<std::is_arithmetic<LowerBound>,
                                      std::is_same<LowerBound, neg_inf>,
                                      std::is_same<LowerBound, pos_inf>>,
                      std::disjunction<std::is_arithmetic<UpperBound>,
                                       std::is_same<UpperBound, neg_inf>,
                                       std::is_same<UpperBound, pos_inf>>
                      >;

另一种方式是static_assert:

template <typename dX, class LowerBound, class UpperBound>
class limit
{
    static_assert(std::is_arithmetic<dX>::value, "!");
    static_assert(std::is_arithmetic<LowerBound>::value
                  || std::is_same<LowerBound, neg_inf>::value
                  || std::is_same<LowerBound, pos_inf>::value, "!");
    static_assert(std::is_arithmetic<UpperBound>::value
                  || std::is_same<UpperBound, neg_inf>::value
                  || std::is_same<UpperBound, pos_inf>::value, "!");
    // ...
};

关于c++ - 指定类模板参数的要求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56657847/

相关文章:

c++ - 如何在 C++ 程序中使用异常?

c++ - 从模板类继承

c++ - 我可以像函数参数的 std::optional 那样使模板参数可选吗?

c++ - 链接 vc6 dll/lib 时未解析的符号

c++ - C和C++中inline-keyword的区别

c++ - 将 BST 转换为排序双向链表(调试)

javascript - Json 数据未使用each append 到Meteor 模板中

git - Azure - 使用arm模板从Visual Studio部署Web应用程序,连接到VSTS git源代码控制

c++ - C++ 变量模板是内联的吗?

c++ - 访问 std::variant 中的公共(public)结构成员