【问题标题】:C++ Type Traits: enable_if -- can this be simplified?C++ 类型特征:enable_if——这可以简化吗?
【发布时间】:2022-08-08 19:48:04
【问题描述】:

这有点丑。这是用 C++17 编写的最简单、最易读的方法,还是可以进一步清理?

template <typename T, std::enable_if_t<std::is_arithmetic_v<T>, bool> = true>
T increment(T v) {
    ...
}

我能想到的最好的方法是将其添加到包含文件中:

template <typename T>
using IsArithmetic = std::enable_if_t<std::is_arithmetic_v<T>, bool>;

然后像这样使用它:

template <typename T, IsArithmetic<T> = true>
T increment(T v) {
    ...
}

有更好的解决方案吗?

  • 我推荐std::nullptr_t = nullptr 而不是bool = true,以通过手动传递参数来防止多个实例化的可能性。否则对我来说看起来不错,我认为没有宏就不能进一步缩短。
  • @Joseph - 你最好的简化基本上是 C++17 能做的最好的。甚至标准库实现也使用它或它的一个版本。鉴于它们是由知识最渊博的专家编写的,我认为我们不能做得更好。
  • 在返回类型中使用 SFINAE 可能看起来更好:template &lt;typename T&gt; std::enable_if_t&lt;std::is_arithmetic_v&lt;T&gt;, T&gt; increment(T v) {/*..*/}
  • 我想我已经看过REQUIRES MACRO。不确定它是否在 C++17 中有所作为:/
  • @HolyBlackCat,在返回类型上使用enable_if 不是更好吗?这样你就永远无法覆盖它......

标签: c++ c++17 typetraits


【解决方案1】:

您可以定义一个名为Requires 的类型别名,而不是专门定义IsArithmetic

#include <type_traits>

template<typename... Cond>
using Requires = std::enable_if_t<std::conjunction_v<Cond...>, bool>;

然后像这样使用它

template <typename T, Requires<std::is_arithmetic<T>> = true>
T increment(T v) {
  // ...
}

【讨论】:

  • 啊,有趣。不一定更短,但它是一个更通用的解决方案,适用于任何谓词,并不特定于 is_arithmetic。
  • 这个技巧在implementations of libstdc++ 中也很常见。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-05
  • 2018-04-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多