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

Fel*_*elk 6 c++ templates generic-programming type-alias c++17

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

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

template <typename T>
using NumberWithSemantics = int;
Run Code Online (Sandbox Code Playgroud)

但问题是所有实例化,无论类型如何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
}
Run Code Online (Sandbox Code Playgroud)

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

Dan*_*l H 5

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

typedef int MyType;
Run Code Online (Sandbox Code Playgroud)

或者

using MyType = int;
Run Code Online (Sandbox Code Playgroud)

你告诉编译器,“无论何时你看到MyType,假装你刚刚看到了int”。那么和之间就没有任何区别了;两者都创建了一个名为type的变量。使声明成为模板无济于事;所有类型都等价地表示.MyType iint iiintusingint

您想要做的是创建一个实际的新类型。为此,您需要使用structor来声明它class,而不仅仅是using. 即使它们看起来相同,类型系统也会将每个以这种方式创建的新类型视为一个单独的类型;通过扩展,如果你制作一个模板struct,每个实例化将是一个新类型。

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

template <typename T>
struct NumberWithSemantics { int i; };
Run Code Online (Sandbox Code Playgroud)

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