当我使用 typedef 或 using for int 时,它仍然是一个 int 有多少?

When I use typedef or using for an int, how much is it still an int?

我尝试了以下方法:

using Idx = int;
array<Value, N> arr;

for(Idx i = 0; i < N; i ++){
  arr[i].doSomething();
}

当我尝试将 Idx 当作 int 使用时,我预计编译器会发出警告或错误。但事实并非如此。

那么,当我使用 usingtypedef 将类型 A 别名为 B 时,类型 B 的变量是否仍然属于类型 A,反之亦然?因此当类型看起来相同但含义不同时,通过重命名类型无法实现类型安全。

(这与我最近问的以下问题有关:

别名声明或 typedef 只是为别名类型创建一个新名称。在这种情况下,Idxint 不是不同的类型;它们可以互换使用,语义上没有区别。

来自 [dcl.typedef](强调我的):

A name declared with the typedef specifier becomes a typedef-name. Within the scope of its declaration, a typedef-name is syntactically equivalent to a keyword and names the type associated with the identifier in the way described in Clause 8. A typedef-name is thus a synonym for another type. A typedef-name does not introduce a new type the way a class declaration or enum declaration does.

typedef 和等效的 using 语句不会增加任何类型安全性,因为它们为 same 类型引入了替代标识符。

有时希望轻松创建不同的类型,您可能会遇到这样的事情:

template <typename T, size_t Id>
struct Distinct_Type
{
    explicit Distinct_Type(const T& t) : t_(t) { }
    const T& get() const { return t_; }
    ...whatever else...
    T t_;
};

用法如:

typedef Distinct_Type<int, __LINE__> Age;
void f(Age);
void g() { f(Age(88)); /*forced explicit construction*/ }

显然 __LINE__ 是一个令人讨厌且容易出错的 hack:使用 C++11 可以创建可靠工作的编译时增量值,但代码太长而无法在此处重新创建和包含 - google 如果有兴趣。

虽然这些真正不同的类型存在问题:例如,如果您调用像 template <typename T> void f(T t); ala f(Distinct_Type<int, 1>(1));f(Distinct_Type<int, 2>(1));f(Distinct_Type<int, 3>(1)); 这样的函数 - compiler/linker 可能会也可能不会从可执行映像中消除三个实例化中的两个,从而减少代码膨胀。

最好有一种从内置类型派生 classes 的简单方法,尤其是在禁用自动转换的情况下。例如,可以为英尺和米定义不同的整数 classes,防止出现导致 Mars Orbiter Crash in 1999. Ada with its focus on safety provides that feature. The reason why it is not possible in C++ is provided in another answer 的错误(那里的 OP 试图从 int 显式继承): int 的 C 类型系统"chaotic" (Stroustrup) 使得这些类型不适合在 class 层次结构中构建块。

就像在 C++ 中一样,必须编写一个包装器,其中包括您想要拥有的所有操作,在 Ada 的情况下会自动提供。