泛型类型别名,它们彼此不兼容

generic type alias, which are incompatible to each other

本文关键字:不兼容 别名 泛型类型      更新时间:2023-10-16

我正在尝试构造某种"泛型类型别名",这意味着我想将类型定义为int例如,但使用泛型类型参数,然后使其与其他类型的实例不兼容。

我尝试使用别名模板执行此操作:

template <typename T>
using NumberWithSemantics = int;

但这样做的问题是,所有实例化,无论类型如何T,都被认为是相等的,例如:

struct A {};
struct B {};
NumberWithSemantics<A> getThing() {
return 14;
}
int processDifferentThing(NumberWithSemantics<B> b) {
return b * 3;
}
int main() {
auto a = getThing();
return processDifferentThing(a); // unfortunately compiles just fine
}

有没有办法定义某种不允许混合不同模板实例化的泛型类型别名?

C++具有类型别名,但它只是类型别名。当你说

typedef int MyType;

using MyType = int;

你告诉编译器,"每当你看到MyType时,假装你刚刚看到了int"。那么MyType iint i之间根本没有区别;两者都创建一个名为iint类型的变量。将using声明设置为模板无济于事;所有类型等同地表示int

您要做的是创建一个实际的新类型。为此,您需要用structclass声明它,而不仅仅是using.即使它们看起来相同,类型系统也会将通过这种方式创建的每个新类型视为单独的类型;推而广之,如果您将模板设为struct,则每个实例化都将是一个新类型。

因此,最小的潜在解决方案是:

template <typename T>
struct NumberWithSemantics { int i; };

然后,您可以将NumberWithSemantics<A>NumberWithSemantics<B>用作不同的类型。但是,您需要不断说.i才能获得实际值,这可能会使您的代码更难阅读。有多种可能的方法可以解决这个问题,为此我建议阅读有关 Fluent C++ 的强类型系列的这一部分。