我想为 double
的不同含义添加编译时检查.在现实世界中,我试图确保所有计算都以一致的单位进行。出于这个问题的目的,我编造了一个玩具示例,其中数字有味道。
我一直在尝试基于模板参数来实现这一点。使用 another answer 中描述的 c++0x 别名功能,我声明了一个 Number<Flavor>
作为:
enum Flavor { Cherry, Plum, Raspberry };
template <Flavor> using Number = double;
这使我能够将局部变量或参数声明为特定类型的 Number,然后在大多数情况下将这些变量用作普通 double 。
我的问题是,我找不到一种方法来声明一个只接受特定风格作为其参数的函数:
void printCherryNumber(Number<Cherry> num) { cout << num << endl; }
int main() {
Number<Cherry> a(5);
Number<Plum> b(6);
Number<Raspberry> c(3.1415);
printCherryNumber(a);
printCherryNumber(b); // O, if only this could be a compiler error.
return 0;
}
我的目标是制作 printCherryNumber(b)
编译失败,因为 b
是 Number<Plum>
不是Number<Cherry>
.许多现有问题使用似乎不适用于我用于 Number
的类型别名构造的解决方案来解决此问题的变体。 .
我试过的东西
来自 this answer ,我看到了添加函数的模板版本的建议,该版本明确不执行任何操作或中断,如
template <typename T> void printCherryNumber(T num) = delete;
这根本没有效果,为什么会这样呢? Number<Plum>
真的是double
和 Number<Cherry>
也是double
所以编译器永远不会为模板版本烦恼。
Another answer建议使用单个模板函数和静态断言,如:
template <Flavor F> void printPlumNumber(Number<F> num) {
static_assert(F == Plum, "Wrong number flavor!");
cout << num << endl;
}
这失败了,因为不管 F
的实际值如何, Number<F>
仍然只是double
所以我得到一个关于无法推断 F
值的错误.
别处有人suggests explicit specialization ,在这种情况下也失败了:
template <Flavor F> void printRaspberryNumber(Number<F> num) = delete;
template <> void printRaspberryNumber<Raspberry>(Number<Raspberry> num) {
cout << num << endl;
}
在这里,编译器将调用视为不明确的,部分原因是它无法推断出 F
的值。 .
房间里的大象
我当然可以制作Number
template <Flavor> struct Number { double value; };
但我试图避免这个选项,因为我对拥有 .value
的想法并不十分兴奋。在我的代码中到处都是,我也不是特别渴望为 Number
定义运算符这只是代理到两倍。
强制性ideone
最佳答案
这种方法的问题:
enum Flavor { Cherry, Plum, Raspberry };
template <Flavor> using Number = double;
是别名模板是透明的。 Number<Cherry>
, Number<Plum>
, 和 double
都是同一类型。这根本无法解决您的问题。
您想要的通常称为不透明类型定义。你真的想要你的最后一个选择:
template <Flavor>
struct Number {
double value;
operator double() const { return value; } // for convenience
Number& operator=(double ); // if necessary
// possibly more operations
};
这边,Number<Cherry>
和 Number<Plum>
是不同的类型。它们不能相互转换。和 double
不能隐式转换为任何一个。
你也可以看看 BOOST_STRONG_TYPEDEF
及其实现,也是为了解决这个问题。
关于c++ - 如何防止模板化别名的隐式保值转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38649229/