Allow implicit conversion for a single value

I have a Flags class that behaves similarly to std::bitset , which replaces bitpacked integers in the old code base. To ensure compliance with the new class, I want to prohibit implicit conversion from int types.

 enum class Flag : unsigned int { none = 0, A = 1, B = 2, C = 4, //... }; class Flags { public: Flags(); Flags(const Flag& f); explicit Flags(unsigned int); // don't allow implicit Flags(const Flags&); private: unsigned int value; }; 

I would like to allow implicit build and assignment only of types Flag and Flags . However, I still like some function calls that take the Flags parameter to accept a literal 0 , but not other integers:

 void foo(const Flags& f); foo(Flags(0)); // ok but ugly foo(1); // illegal because of explicit constructor foo(0); // illegal, but I want to allow this 

Is it possible? To allow 0 be implicitly converted when forbidding other values?

+5
source share
1 answer

One approach:

Add a constructor that accepts void* .

Since the literal 0 implicitly converted to the null pointer void* , and the literal 1 isn`t, this will give the desired behavior. For security, you can argue that the pointer has a null value in ctor.

The downside is that now your class is constructive from nothing implicitly convertible to void * . Some unexpected things are so convertible - for example, before C ++ 11, std::stringstream was converted to void* , basically how to hack, because an explicit operator bool did not exist yet.

But this can work great in your project if you are aware of potential pitfalls.

Edit:

Actually, I remembered how to make it safer. Instead of void* use a pointer to a private type.

It might look like this:

 class Flags { private: struct dummy {}; public: Flags (dummy* d) { ... } ... }; 

Literal conversion 0 will still work, and for some user-defined type will be unpredictably inadvertently converted to Flags::dummy * .

+6
source

Source: https://habr.com/ru/post/1268789/


All Articles