【问题标题】:Dependent types in c++, a non zero typec++中的依赖类型,非零类型
【发布时间】:2017-04-04 13:58:35
【问题描述】:

让我们说这是一个非零能类型的裸骨。

template<typename T>
struct NonZero {
    T val;
};

我的问题是是否可以为 NonZero 创建一个构造函数,该构造函数采用 T 类型的文字并静态检查它是否非零,然后将其分配给 val

NonZero<int> n( 0 ); // compilation error
NonZero<int> n( 1 ); // ok

或者有没有更好的方法来归档非零类型?

【问题讨论】:

  • 据我了解,具体实现只能通过模板特化来提供;这是我们想要的吗?
  • 我想知道是否有更简单的方法,因为NonZero&lt;int&gt; n( var ) 也应该是可能的。

标签: c++ types


【解决方案1】:

由于值在编译时已知,您可以将其作为模板参数并使用std::enable_if

template<typename T, T x>
struct NonZero {
    const static std::enable_if_t<x != T(0), T> value = x;
};

用法:

int x = NonZero<int, 1>::value; // OK
int x2 = NonZero<int, 0>::value;// Compilation error

【讨论】:

  • 谢谢,我注意到我的问题有点含糊。还需要一个具有左值 int 的构造函数。
  • @Sherushe 然后看起来我的另一个答案是一个好主意。
【解决方案2】:

另一种选择是检查 constexpr 构造函数中的值是否为零:

template<typename T>
struct NonZero {
    const T value;
    constexpr NonZero(const T val) :
        value(val != 0 ? val : throw std::runtime_error("should be non-zero"))
    {}
};

用法:

NonZero<int> v(1);            // OK
NonZero<int> v2(0);           // Compiles OK, but throws in run-time
constexpr NonZero<int> v3(1); // OK
constexpr NonZero<int> v4(0); // Compilation error

这种方法只适用于constexpr变量,但看起来更直接。

此外,您可以使用 constexpr 函数或用户定义的文字,而不是使用 structconstexpr 构造函数,具有完全相同的想法。

【讨论】:

  • 我只是在 gcc 中遇到错误,说 expression '&lt;throw-expression&gt;' is not a constant-expression。你知道这个问题吗?
  • 我太傻了,别管我的评论了,当变量用0构造时当然会出现编译错误。无论如何谢谢你,这正是我要找的。​​span >
  • @Sherushe 不客气。这是一个很好的问题。
【解决方案3】:

刚刚想到了另一种方法,它将为您提供一个将值作为参数的构造函数。

核心思想是将构造函数模板化并将值作为模板参数传递。不幸的是,不可能以直接的方式做到这一点,但我们可以使用this question 中的解决方法:

template<typename T>
struct NonZero {
    const T value;

    template<T x>
    NonZero(std::integral_constant<std::enable_if_t<x != T(0), T>, x>) : value(x) {
    }
};

用法:

auto v  = NonZero<int>(std::integral_constant<int, 1>()); // OK
auto v2 = NonZero<int>(std::integral_constant<int, 0>()); // Compilation error

【讨论】:

    猜你喜欢
    • 2015-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    相关资源
    最近更新 更多