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

时间:2015-10-04 21:38:30

标签: c++ c++11 overloading alias typedef

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

using String = std::string;

void Print(String s) { ... };

但是,这并不禁止使用Print调用std::string

Print(std::string{"Hello world"}); // Still works

这是有道理的 - 别名严格用于简化类型的名称,它不定义新类型。

除了子类化,即not a good idea之外,还有一种机制可以通过名称为函数参数实现严格的输入吗?这样做的直接后果是这也是可能的:

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

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

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

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

3 个答案:

答案 0 :(得分:2)

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

  

7.1.3 / 1:使用typedef指定器声明的名称将成为typedef-name。在其声明的范围内,typedef-name是   在语法上等同于关键字并命名关联的类型   使用第8章中描述的方式识别标识符。一个typedef-name   因此是另一种类型的同义词。 typedef-name不会引入   一个新类型类声明或枚举声明的方式。

  

7.1.3 / 2:也可以通过别名声明引入typedef-name。 using关键字后面的标识符变为a   typedef的名称。它具有与引入时相同的语义   typedef speci fi er。特别是,它并没有定义一种新的类型   它不应出现在type-id。

所以不幸的是,你将不得不继续使用你的类包装器来引入不同的类型,并能够在这个基础上重载函数。

答案 1 :(得分:2)

不,如果没有实际创建新类型(class,struct,enum),就无法获得新类型。

但是,有a brand new proposal添加此类机制,可能使用newtype作为关键字而不是typedef

答案 2 :(得分:2)

你采取了正确的方法。包装原始类型的对象是您目前可以做的最好的。

我最近在CppCon 2015上讨论了这个主题,并开源了一个库,可以方便地制作一个" opaque typedef"对于整数类型: https://sourceforge.net/projects/opaque-typedef/

请注意,定制新类型的界面,删除可能出于您的目的的错误操作以及添加与其他类型的故意互操作性可能是有益的。 Slides from my presentation