为什么专门化type_trait会导致未定义的行为?

101*_*010 6 c++ undefined-behavior language-lawyer c++11 c++14

讨论

根据标准§20.10.2/ 1标题<type_traits>提要[meta.type.synop]:

1 除非另有说明,否则为本子条款中定义的任何类模板添加特殊化的程序的行为是未定义的.

这个特定的条款与STL应该是可扩展的一般概念相矛盾,并且阻止我们扩展类型特征,如下例所示:

namespace std {
template< class T >
struct is_floating_point<std::complex<T>> : std::integral_constant
         <
         bool,
         std::is_same<float, typename std::remove_cv<T>::type>::value  ||
         std::is_same<double, typename std::remove_cv<T>::type>::value ||
         std::is_same<long double, typename std::remove_cv<T>::type>::value
         > {};
}
Run Code Online (Sandbox Code Playgroud)

LIVE DEMO

其中std::is_floating_point扩展为处理complex具有基础浮点类型的数字.

问题

  1. 是什么原因使标准化委员会决定类型特征不应该是专业化的.
  2. 是否有任何未来的计划可以撤回此限制.

How*_*ant 11

对于主要类型类别(即is_floating_point1),有一个设计不变量:

对于任何给定类型T,其中一个主要类型类别具有一个计算结果的值成员true.

参考:(20.10.4.1主要类型类别[meta.unary.cat])

在检查一些未知的泛型类型时,程序员可以依赖于通用代码中的这个不变量T:即如果is_class<T>::valuetrue,则我们不需要检查is_floating_point<T>::value.我们保证后者是false.

下图是表示主要和复合类型特征的图表(此图顶部的叶子是主要类别).

http://howardhinnant.github.io/TypeHiearchy.pdf

如果允许有(例如)std::complex<double>回答真既is_classis_floating_point,这个有用不变将被打破.程序员将不再能够依靠的事实是,如果is_floating_point<T>::value == true,则T必须是一个float,doublelong double.

现在有一些特征,标准"另有说法",并且允许对用户定义类型进行专门化. common_type<T, U>是这样的特质.

对于主要和复合类型的特征,没有计划放宽对这些特征进行专门化的限制.这样做会损害这些特征对C++中可生成的每种类型进行精确和唯一分类的能力.

  • 还有一种"不变"的类型,主要类型的特征也反映了真相.也就是说,诸如"浮点类型"的类别在标准中具体描述 - 并且它们非常不可扩展或用户可定制.因此,用户定义的专业化将重新陈述显而易见的或谎言. (2认同)