自学 Rust 后,我成为了 newtype 惯用语 的粉丝,我认为 Rust 从 Haskell 借鉴了这个惯用语。
新类型是一种基于标准类型的独立类型,它确保函数参数具有正确的类型。例如,下面的
什么是在C++中实现newtype惯用法的最佳方法?是否有标准方法?
编辑问题使用强类型和typedef类似。然而,它没有考虑到newtype惯用法。
新类型是一种基于标准类型的独立类型,它确保函数参数具有正确的类型。例如,下面的
old_enough
函数必须传入年龄。如果传入天数或纯 i64,则无法编译。struct Days(i64);
struct Years(i64);
fn old_enough(age: &Years) -> bool {
age.0 >= 18
}
这与C++中的typedef
或using
声明不同,它只是简单地重命名类型。
例如下面的old_enough
函数将接受一个int
、一个以Days
为单位的年龄或任何其他可以转换为int
的内容:
typedef int Days;
using Years = int;
bool old_enough(Years age) {
return age >= 18;
}
正如上面的示例仅使用整数,这篇 Reddit 帖子建议使用枚举类,例如:
enum class Days : int {};
enum class Years : int {};
bool old_enough(Years age) {
return static_cast<int>(age) >= 18;
}
或者它可以简单地使用结构,例如Rust:
struct Days final {int value;};
struct Years final {int value;};
bool old_enough(Years age) {
return age.value >= 18;
}
什么是在C++中实现newtype惯用法的最佳方法?是否有标准方法?
编辑问题使用强类型和typedef类似。然而,它没有考虑到newtype惯用法。
Year
类,并在构造函数和/或赋值级别上进行验证。比如auto year = new Year(2002)
然后year.old_enough()
,或者对于更严格的实现,当提供无效值时会throw
异常。 - tadmanBOOST_STRONG_TYPEDEF
,但总的来说我同意 tad 的观点,一个“年份”不是一个“整数”,它应该有自己的类型。 - 463035818_is_not_a_numberauto year = Year(2002);
。 - user253751std::chrono::years
和std::chrono::days
,它们本质上已经是这种类型的包装器了。(尽管在这种情况下,还可以从例如std::chrono::days
到std::chrono::seconds
的隐式转换,其背后的实现将通过正确的转换因子乘以该值。)Boost还有一个单位库,它处理将双精度值包装在SI(或英制单位)中,并在幕后进行转换。 - Daniel Schepler