你可以不用标题:
using size_t = decltype(sizeof(int));
using size_t = decltype(sizeof 1); // The shortest is my favourite.
using size_t = decltype(sizeof "anything");
这是因为 C++ 标准要求:
sizeof 和sizeof... 的结果是std::size_t 类型的常量。 [注:std::size_t 在标准头文件<cstddef> (18.2) 中定义。 ——尾注]
换句话说,标准要求:
static_assert(std::is_same<decltype(sizeof(int)), std::size_t>::value,
"This never fails.");
还请注意,在全局和 std 命名空间中创建此 typedef 声明是完全可以的,只要它与相同 typedef-name 的所有其他 typedef 声明匹配em>(对不匹配的声明发出编译器错误)。
这是因为:
怀疑论者说这构成了在命名空间std 中添加新类型,而这种行为被标准明确禁止,这就是 UB,仅此而已;不得不说,这种态度等于无视和否认对根本问题的更深理解。
标准禁止在命名空间std 中添加新的声明和定义,因为这样做用户可能会弄乱标准库并打断他的整条腿。对于标准编写者来说,让用户专注于一些特定的事情并禁止做任何其他事情会更容易,而不是禁止用户不应该做的每一件事,并冒着错过重要事情(和那条腿)的风险。他们过去在要求任何标准容器都不应使用不完整类型实例化时这样做,而实际上某些容器可以做到(参见The Standard Librarian: Containers of Incomplete Types by Matthew H. Austern):
... 到头来,这一切都显得太模糊,太难理解了;标准化委员会认为除了说 STL 容器不应该与不完整的类型一起使用之外,别无选择。为了更好地衡量,我们也将该禁令应用于标准库的其余部分。
... 回想起来,既然对技术有了更好的理解,那个决定似乎仍然基本上是正确的。是的,在某些情况下,可以实现一些标准容器,以便可以使用不完整的类型对其进行实例化——但也很清楚,在其他情况下,这将是困难的或不可能的。我们使用std::vector 尝试的第一个测试碰巧是一个简单的案例,这主要是偶然的。
鉴于语言规则要求 std::size_t 与 decltype(sizeof(int)) 完全一致,因此执行 namespace std { using size_t = decltype(sizeof(int)); } 是不会破坏任何东西的事情之一。
在 C++11 之前,没有 decltype,因此无法在一个简单的语句中声明 sizeof 的类型,而无需涉及大量模板。 size_t 为不同目标架构上的不同类型别名,然而,仅仅为sizeof 的结果添加新的内置类型并不是一个优雅的解决方案,并且没有标准的内置类型定义。因此,当时最便携的解决方案是将size_t 类型别名放在某个特定的标题中并记录下来。
在 C++11 中,现在有一种方法可以将标准的确切要求写成一个简单的声明。