1

假设我想为整数类型而不是字符做一些事情,我有

is_integral<T>::typeis_char<T>::type

是否可以这样写:

integral_constant<bool,is::integral<T>::value && !is_char<T>::value>

更具可读性

4

2 回答 2

3

这些元计算甚至在 C++11 之前就已经完成,而Boost.MPL是 C++03 中 TMP 的重炮。有了它,您的要求可以这样表达:

// in C++03:
// typedef /* compute */ result;
using result = and_<is_integral<T>, not_<is_char<T>>>;

(来自命名空间的位置and_和位置。)not_boost::mpl

请注意有限的冗长,因为您不必使用::value样板。同样,result它是惰性的,您可以在其中强制使用result::value(将是trueor false)或result::type(这将是一个类型——文档包含所有详细信息)来强制计算结果。Boost.MPL 很容易不这样做,因此例如not_<result>足以反转逻辑,即使not_<result::type>也可以工作。typename考虑到如果依赖,则需要附加项是一件好事result

我确实认为 Boost.MPL 在 C++03 中有巨大帮助,部分原因是它模拟了可变参数模板。例如,and_不限于两个参数。我在 C++11 中避开了它,但是因为在我使用它的大多数情况下,我现在使用包扩展。尽管如此,类似的东西and_仍然有用,因为不可能在任意表达式中扩展包,例如在涉及&&逻辑运算符的表达式中。这只能通过逻辑元函数来完成:

// Enforce precondition: every type T must be integral
static_assert( and_<std::is_integral<T>...>::value, "Violation" );

我认为这篇文章是一本很好的读物,它给出了减少元计算冗长的很好的提示。它侧重于用于通用编程的 SFINAE,但它也适用于 TMP(SFINAE 也可用于 TMP)。最后一个例子是

template <typename T,
          EnableIf<is_scalable<T>, is_something_else<T>>...>
T twice(T t) { return 2*t; }

在 C++03 中可能看起来像这样,使用类似于 Boost 中提供的工具:

template<typename T>
typename enable_if<
    and_<is_scalable<T>, is_something_else<T>>
    , T
>::type twice(T t) { return 2*t; }

一个天真的 C++11 版本可以说是最糟糕的:

template<typename T>
typename std::enable_if<
    is_scalable<T>::value && is_something_else<T>::value
    , T
>::type twice(T t) { return 2*t; }

我见过一些主张放弃 Boost.MPL 风格的人,Boost.MPL 倾向于使用类型和类型“返回”元函数来使用值和constexpr函数。这可能看起来像:

// EnableIf alias now accepts non-type template parameters
template<typename T
         , EnableIf<is_scalable<T>() && is_something_else<T>()>...>
T twice(T t) { return 2*t; }

你仍然需要一个constexpr函数来计算例如逻辑析取如果T...是一个包虽然:EnableIf<any(is_foo<T>()...)>.

于 2012-09-29T20:04:19.070 回答
1

为什么需要积分常数?如果您只需要一个编译时常量 bool,那么您不必包装表达式。

is_integral<T>::value && !is_char<T>::value

如果你在几个地方需要这个表达式,你可以写你自己的特殊类型特征。

template<typename T>
struct is_integral_and_not_char {
    static const bool value = is_integral<T>::value && !is_char<T>::value;
};

is_integral_and_not_char<T>::value

或者,如果您确实想符合 UnaryTypeTrait 概念,那么

template<typename T>
struct is_integral_and_not_char
  : std::integral_constant<bool, std::is_integral<T>::value && !std::is_char<T>::value>
{}
于 2012-09-29T19:17:16.930 回答