在C ++ 11中,是否有一种干净的方法来禁用typedef之间的隐式转换,或者你是否需要做一些令人讨厌的事情,比如在类中包装int并定义和删除各种运算符?
typedef int Foo;
typedef int Bar;
Foo foo(1);
Bar bar(2);
bar = foo; // Implicit conversion!
答案 0 :(得分:5)
C ++标准说:
7.1.3 typedef说明符
使用typedef说明符声明的名称将成为typedef-name。在其声明的范围内,typedef-name 在语法上等同于关键字,并命名与标识符相关联的类型 第8章中描述的方式.typedef-name是,因此是另一种类型的同义词。一个typedef-name可以 不按类声明(9.1)或枚举声明
的方式引入新类型
但是,例如class
或struct
引入新类型。在以下示例中,uniqueUnused
实际上只用于创建不同类型Value<int, 1> != Value<int, 2>
。所以也许这是你正在寻找的东西。 请记住,无法保证编译器摆脱外部结构!这个代码的唯一保证是它与int
template<typename T, int uniqueUnused>
struct Value
{
Value() : _val({}) {}
Value(T val) : _val(val) { }
T _val;
operator T&() { return _val; }
// evaluate if you with or without refs for assignments
operator T() { return _val; }
};
using Foo = Value<int, 1>;
using Bar = Value<int, 2>;
static_assert(sizeof(Foo) == sizeof(int), "int must be of same size");
static_assert(sizeof(Bar) == sizeof(int), "int must be of same size");
如果你想基于一个类创建一个新类型,你可以简单地使用这个例子(这不适用于标量类型,因为你不能从int继承):
class Foo : public Bar // introduces a new type called Foo
{
using Bar::Bar;
};
答案 1 :(得分:5)
HelloWorld解释了为什么你所拥有的不起作用。你需要通常所说的“强大的”#34; typedef
做你想做的事。示例实现是BOOST_STRONG_TYPEDEF
:
#include <boost/serialization/strong_typedef.hpp>
BOOST_STRONG_TYPEDEF(int, a)
void f(int x); // (1) function to handle simple integers
void f(a x); // (2) special function to handle integers of type a
int main(){
int x = 1;
a y;
y = x; // other operations permitted as a is converted as necessary
f(x); // chooses (1)
f(y); // chooses (2)
}
如果我们完成了typedef int a;
,那么代码就会模糊不清。
答案 2 :(得分:0)
我想做一些类似的事情,不仅在逻辑上保持不同的索引分开,而且还由编译器强制执行。我想出的解决方案基本上是用一个元素定义结构。在某些方面,它使用起来更痛苦,但它对我的情况非常有效,因为我经常不需要处理很多代码的索引的实际值,只需传递它即可。
typedef struct{uint16_t i;} ExpressionIndex;
typedef struct{uint16_t i;} StatementIndex;
现在,尝试做
ExpressionIndex foo() {
StatementIndex i;
return i;
}
产生错误 error: incompatible types when returning type ‘StatementIndex’ but ‘ExpressionIndex’ was expected
类型之间的转换有点痛苦,但这就是我改变的意图。
ExpressionIndex exp = (ExpressionIndex){stmt.i};
答案 3 :(得分:-1)
不是严格的类型检查,但非法转换可以使用原始或 Apps匈牙利表示法(H.N。)进行可见。如果您认为HN意味着名称类型为前缀,那么您就错了(它的系统HN ,以及它,嗯,不必要的命名开销)。< / p>
使用(Apps)H.N。,变量前缀不是类型(例如 int ),而是目的,例如计数器,长度,秒等等。因此,当您向变量添加一个包含已用时间的计数器时,您可以编写cntSomethingCounter + secElapsedSinceLastSomething
,并且可以看到它有气味。编译器不会发出警报,但它会引起你的注意。