简体   繁体   中英

Declare types without implicit conversion in C++

I want to declare my own numeric types, exactly like unsigned int, but I do not want the types to be implicitly converted. I tried this first: typedef unsigned int firstID; typedef unsigned int secondID;

but this is no good as the two types are just synonyms for unsigned int, so are freely interchangable.

I'd like this to cause an error:

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

but this to be okay:

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

My reason is so that function arguments are strongly typed, eg:

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

What is the mechanism I am looking for?

Thanks

Si

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

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.

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

Ahhh, a fellow Ada traveler I see.

The only real way to do this in C++ is to declare classes. Something like:

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;
};

You'll want to make sure to define your int constructor explicit so that C++ won't use it to implicitly convert between your types. That way this will not work:

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

but something like this might (assuming you define it):

int i = centum.to_int();
struct FirstID { int id; };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM