C++ 使用别名严格键入函数参数

C++ 使用别名严格键入函数参数,c++,c++11,overloading,alias,typedef,C++,C++11,Overloading,Alias,Typedef,可以使用别名更改函数的文字签名: 使用String=std::String; 无效打印(字符串s){…}; 但这并不禁止使用std::string调用Print: Print(std::string{"Hello world"}); // Still works 这很有意义——别名严格来说是为了简化类型的名称,而不是定义新类型 除了子类化,也就是说,是否有一种机制可以实现函数参数按名称严格键入?这样做的直接后果是,这也是可能的: using StringA = std::string; us

可以使用别名更改函数的文字签名:

使用String=std::String;
无效打印(字符串s){…};
但这并不禁止使用
std::string
调用
Print

Print(std::string{"Hello world"}); // Still works
这很有意义——别名严格来说是为了简化类型的名称,而不是定义新类型

除了子类化,也就是说,是否有一种机制可以实现函数参数按名称严格键入?这样做的直接后果是,这也是可能的:

using StringA = std::string;
using StringB = std::string;

void Print(StringA s) { ... };
void Print(StringB s) { ... };

Print(StringA{"Hello world"});
Print(StringB{"Hi everyone"});

我当前的解决方案是定义简单的包装类,这些包装类包含我想要作为成员别名的类型。这并不理想,因为它需要将成员类的接口复制到包装器中,这在使用别名时是不必要的。

该标准使typedefs和alias成为另一种类型的同义词,而不是新类型:

7.1.3/1:使用typedef规范声明的名称将成为typedef名称。在其声明的范围内,typedef名称是 语法上等同于关键字并命名关联的类型 按照第8条所述的方式使用识别器类型定义名称 因此是另一种类型的同义词。typedef名称不会引入 新类型与类声明或枚举声明的方式相同

7.1.3/2:别名声明也可以引入typedef名称。using关键字后面的标识符将成为 typedef名称。它的语义与 typedef规范。特别是,它没有定义新的类型和类型 它不应出现在type-id中


所以不幸的是,您必须继续使用类包装器来引入不同的类型,并能够在此基础上重载函数

不,如果不实际创建新类型(类、结构、枚举),就无法获取新类型


然而,有必要添加这样一种机制,也许使用
newtype
作为关键字,而不是
typedef

您采取了正确的方法。包装原始类型的对象是当前所能做的最好的操作

我最近在CppCon 2015上谈到了这个话题,并公开了一个库,它可以方便地为整数类型创建“不透明类型定义”:


请注意,自定义新类型的接口、删除可能会导致错误的操作以及添加与其他类型的有意互操作性都是有益的

请注意,第二个答案表明,在您的情况下创建派生类可能是合理的,如果您小心的话:这是一个优秀的分析。谢谢你指出这一点,我经常忽略未经选择的答案,但这是一个令人谦卑的阅读。我真的看到了你的演讲(我是你小组中的闪电演讲人之一),这让我质疑是否已经有了一个用于不透明typedef的语言机制。