【问题标题】:generic type alias, which are incompatible to each other泛型类型别名,彼此不兼容
【发布时间】:2018-11-15 11:49:12
【问题描述】:

我正在尝试构建某种“泛型类型别名”,这意味着我想将一个类型定义为例如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
}

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

【问题讨论】:

  • 我建议阅读 Fluent C++ 上的 strong types series。你最感兴趣的部分可能是the second article
  • 谢谢,按照这个建议,对我来说最简单的解决方案是将using NumberWithSemantics = int; 替换为struct NumberWithSemantics { int value; }
  • 如果有人能解释为什么模板结构准确起作用而模板别名不起作用,我会有一个可以接受的答案:)

标签: c++ templates c++17 generic-programming type-alias


【解决方案1】:

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

typedef int MyType;

using MyType = int;

你告诉编译器,“每当你看到MyType,就假装你刚刚看到int”。那么MyType iint i 之间根本没有区别;两者都创建了一个名为 i 的变量,类型为 int。使using 声明成为模板并没有帮助;所有类型都等价于int

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

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

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

然后您可以将NumberWithSemantics&lt;A&gt;NumberWithSemantics&lt;B&gt; 用作不同的类型。但是,您需要一直说.i 才能得到实际值,这会使您的代码更难阅读。有多种可能的方法来解决这个问题,我建议阅读 Fluent C++ 上的强类型系列的 this part

【讨论】:

    猜你喜欢
    • 2018-08-16
    • 2015-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-28
    • 2019-09-06
    相关资源
    最近更新 更多