使用别名严格键入函数参数
Using aliases for strictly typing function parameters
可以使用别名来更改函数的文字签名:
using String = std::string;
void Print(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"});
我目前的解决方案是定义简单的包装器类,其中包含我想要作为成员别名的类型。这并不理想,因为它需要将成员类的接口复制到包装器中,而使用别名时则不需要这样做。
你的做法是正确的。包装原始类型的对象是目前你能做的最好的事情。
我最近在CppCon 2015上谈到了这个话题,并且开源了一个库,可以方便地为整数类型创建一个"不透明的类型定义":https://sourceforge.net/projects/opaque-typedef/
请注意,自定义新类型的接口、删除对您的目的来说可能是错误的操作以及有意添加与其他类型的互操作性可能是有益的。我的演讲幻灯片
标准使typedefs和alias成为另一种类型的同义词,而不是新类型:
7.1.3/1:用typedef说明符声明的名称变成typedef-name。在其声明的范围内,typedefine -name为语法上等同于关键字,并命名相关联的类型用第8条中描述的方式进行标识。类型名因此是另一类型的同义词。typedefine -name不引入一个新的类型,就像类声明或enum声明所做的那样。
和
因此,不幸的是,您将不得不继续使用类包装器来引入不同的类型,并能够在此基础上重载函数。7.1.3/2: typedefine -name也可以通过别名声明引入。using关键字后面的标识符变成类型名。它具有相同的语义,就好像它是由类型定义说明符。特别是,它没有定义新的类型和它不能出现在类型id中。
不,如果不实际创建新类型(class, struct, enum),就无法获得新类型。
然而,有一个全新的建议来添加这样的机制,可能使用newtype
作为关键字而不是typedef
。
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当从函数参数中的临时值调用复制构造函数时
- 如何从"decltype()"获取函数参数的数量<funtion>?
- 如何将lambda作为模板类的成员函数参数
- 模板参数推导失败,函数参数/参数不匹配
- 如何在C++中将迭代器作为函数参数传递
- 将函数参数"const char*"转换为"std::string_view"是
- C++ 如何将数组值解压缩为函数参数
- 主函数参数的属性
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- "Warning: Comma within array index expression"但逗号分隔函数参数
- 如何定义在用作函数参数时工作的类模板的转换
- 将函数参数完美转发到函数指针:按值传递呢?
- 为什么我不能将引用作为 std::async 的函数参数传递
- 什么..(省略号)作为函数原型中唯一的函数参数,C++?
- 是否可以就地构造一个固定大小的数组作为函数参数?
- 接受模板作为函数参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- Arduino 函数参数