23

类似的问题:为什么type_traits用专门的模板结构而不是 constexpr 来实现?——但有不同的答案。

我意识到别名模板不能专门化,因此目前不能直接用于实现类型特征1。然而,这是委员会有意识的决定,据我所知,没有技术上的理由禁止这样做。

那么将类型特征实现为别名模板并简化它们的语法不是更有意义吗?

考虑

 typename enable_if<is_pointer<T>::value, size_t>::type
 address(T p);

相对

 enable_if<is_pointer<T>, size_t> address(T p);

当然,这在从Boost.TypeTraits迁移时引入了一个重大的界面变化——但这真的是一个大问题吗?

毕竟,代码无论如何都需要修改,因为类型驻留在不同的命名空间中,并且由于许多现代 C++ 程序员不愿意打开命名空间,因此将明确限定(如果它会被更改的话)。

另一方面,它极大地简化了代码。鉴于模板元编程经常变得嵌套、复杂和复杂,显然更清晰的界面是有益的。

我错过了什么吗?如果不是,我会很感激一个不仅仅是猜测的答案,而是依赖于(并且可以引用)委员会决策理由的知识。


1但间接地很好!考虑:

template <typename T> using is_pointer = typename meta::is_pointer<T>::type;

其中meta::is_pointer<T>对应于当前std::is_pointer<T>类型。

4

3 回答 3

16

对您的问题最具体的回答是:从来没有人提议这样做。

C++ 标准委员会是一个多国、多公司的志愿者集合。您将其视为单个组织内的设计委员会。如果没有将文字写入标准草案的提议,C++ 标准委员会实际上无法做任何事情。

我想没有提案的原因是 type traits 是一个早期的提案,boost 的实现可以追溯到 2000 年左右。模板别名的实现也很晚。许多委员会成员不愿意提出他们没有实施的东西。而且几乎没有机会实施您的提案。

发布 C++11 的压力很大。它确实打算在 2009 年发布,但当发布日期不慎时,除了修复已经在考虑中的功能之外,对工作文件做任何事情都非常困难。在某些时候,你必须把伟大的新想法放在次要位置,以免你永远无法出货。

更新

从 C++14 开始,TransformationTraits(产生类型的那些)现在具有模板别名拼写,例如:

template <bool b, class T = void>
  using enable_if_t = typename enable_if<b,T>::type;

C++1z 工作草案现在具有用于产生值的特征的模板变量拼写:

template <class T>
  constexpr bool is_pointer_v = is_pointer<T>::value;

此外,即使在 C++11 中,也可以这样做:

typename enable_if<is_pointer<T>{}, size_t>::type
address(T p);

即你可以使用{}代替::value(假设你的编译器有constexpr支持)。在 C++14 中变成:

enable_if_t<is_pointer<T>{}, size_t>
address(T p);

在 C++1z 中:

enable_if_t<is_pointer_v<T>, size_t>
address(T p);

请注意,C++1z 和 C++14 之间的差异是如此之小,以至于它甚至不保存字符,只是更改{}_v更改了放置这两个字符的位置。

于 2012-02-29T14:53:08.640 回答
2

<memory>类型特征,与包括and在内的其他几个库一样<functional>,都是从 C++ TR1 继承的。虽然那是一个不太正式的文档,但它比 Boost 更正式,而且兼容性是值得的。

另外,请注意类型特征都派生自std::integral_constant<bool>,它确实实现了constexpr到 的转换函数bool。这样至少可以节省::value零件,如果您愿意的话。

于 2012-02-29T14:54:38.583 回答
1

作为一个完整的旁注,因为似乎对别名可能或可能不会帮助以下特征感到困惑std::is_pointer

你可以走 Boost.MPL 路线并决定你将使用 Boost.MPL 风格的整数常量,这意味着类型

template<typename Cond, typename Then = void>
using enable_if = typename std::enable_if<Cond::value, Then>::type;

// usage:
template<
    typename T
    , typename = enable_if<std::is_pointer<T>>
>
size_t address(T p);

或者您可以决定改用值

template<bool Cond, typename Then>
using enable_if = typename std::enable_if<Cond, Then>::type;

// can use ::value
template<
    typename T
    , typename = enable_if<std::is_pointer<T>::value>>
>
size_t address(T p);

// or constexpr conversion operator
template<
    typename T
    , typename = enable_if<std::is_pointer<T> {}>
>
size_t address(T p);

请注意,在后一种情况下,不可能使用enable_if<std::is_pointer<T>()>:std::is_pointer<T>()是一个函数类型(获取void和返回std::is_pointer<T>)并且是无效的,因为我们的别名在这种情况下接受一个值而不是类型。大括号确保它是一个常量表达式。

正如您可能已经注意到的那样,std::is_pointer它根本不会从模板别名中受益。这并不奇怪,因为这是一个有趣的部分正在访问的特征::value,而不是::type:模板别名只能帮助成员类型。的type成员std::is_pointer并不有趣,因为它是一个 Boost.MPL 风格的积分常数(在本例中为std::true_typeor std::false_type),所以这对我们没有帮助。对不起!

于 2012-02-29T22:03:07.747 回答