在C++中声明类型而不进行隐式转换

uqzxnwby  于 2022-12-05  发布在  其他
关注(0)|答案(6)|浏览(151)

我想声明我自己的数字类型,就像unsigned int一样,但是我不想类型被隐式转换。我首先尝试了以下方法:typedef无符号整型firstID; typedef无符号整型secondID;
但这并不好,因为这两种类型只是unsigned int的同义词,因此可以自由互换。
我希望这会导致错误:

firstID fid = 0;
secondID sid = fid; // no implicit conversion error

但这是好的:

firstID fid = 0;
secondID sid = static_cast<secondID>(fid); // no error

我的理由是函数参数是强类型的,例如:

void f( firstID, secondID ); // instead of void f(unsigned int, unsigned int)

我在寻找什么机制?
谢谢
西

ih99xse1

ih99xse11#

也许BOOST_STRONG_TYPEDEF表单boost/strong_typedef.hpp会有所帮助。

gywdnpxw

gywdnpxw2#

As you noted: typedef is badly named (it should be typealias (D has explicitly added typealias (last time I looked))
So the only way you can do this is to create two unique classes.
I am not going to say you can't write a specialization of static_cast<> to do what you want, but I think (and I have not put that much thought into it yet) doing so would be a bad idea (even if it legal), I think a better approach is to have each class constructor use unsigned int that are explicit (so there is no auto conversion).

struct FID
 {
     explicit FID(unsigned int v): value(v) {}
     operator unsigned int() {return value;}
     unsigned int value;
 };

 class SID {/* Stuff */};

 FID   fid(1U);
 SID   sid(2U);

 doSomthingWithTwoSID(sid,SID(static_cast<unsigned int>(fid));

Making the constructor explicit means no auto conversion between types.
By adding the built in cast operator to unsigned int means that it can be used anywhere an int is expected.

cgfeq70w

cgfeq70w3#

您必须为它们编写自己的类,重新实现所需的所有操作符。

mnemlml8

mnemlml84#

struct FirstID { int id; };
41zrol4v

41zrol4v5#

啊,我看到一个艾达的旅伴了。
在C++中,实现这一点的唯一真实的方法是声明类。类似于:

class first_100 {
public:
    explicit first_100(int source) {
        if (source < 1 || source > 100) {
           throw range_error;
        }
        value = source;
    };
    // (redefine *all* the int operators here)
private:
    int value;
};

你需要确保定义int构造函数explicit,这样C++就不会用它来隐式地在类型之间进行转换。

first_100 centum = first_100(55);
int i = centum;

但可能会出现如下情况(假设您定义了它):

int i = centum.to_int();
cidc1ykv

cidc1ykv6#

尊敬的DBJ总是有一个非常有趣的解决方案。这里是他的文章Cpp How to Avoid Implicit Conversions和类型的simple header adding basic operators。就像其他人提到的,它是一个模板化的类,但与我在这里找到的其他答案不同,这里是一个经过测试并能工作的解决方案(呃,除了导入所有boost之外)。
然后在实践中,你可以声明一个类型,而不需要像平常那样进行隐式转换,在头文件中进行 Package 。

using my_safe_uint16_t = dbj::util::nothing_but<uint16_t>;

相关问题