Reputation: 654
I have a flags class witch is just a wrapper around an integer and I want to implement explicit conversion to to arbitrary integers types based on the conversion rules for the underlying integer type.
i.e.
say I have the class along the lines of (ignoring non-relevant members)
class Flags {
unsigned int v;
explicit operator unsigned int() { return v; }
}
could I still convert to an integral type other than int say by
unsigned long long iflags = static_cast<unsigned long long>(flags);
rather than
unsigned long long iflags = static_cast<unsigned int>(flags);
or would I need to explicitly define a conversion operator for every integral type to be able to do this?
Note I'm using C++14
I've read http://en.cppreference.com/w/cpp/language/cast_operator but can't see any thing specific to integral types which makes me think I need to explicit define all valid conversion which I want to avoid. I would also be happy with a template conversion function which will fail if conversion to the target type isn't possible, noting I know the max value of the internal integer i.e. all flag bits turned on, as a macro/constant FLAGS_MAX
, if this is of any use.
Upvotes: 0
Views: 802
Reputation: 206577
could I still convert to an integral type other than int say by
unsigned long long iflags = static_cast<unsigned long long>(flags);
No, you can't.
The above is equivalent to:
unsigned long long temp(flags);
unsigned long long iflags = temp;
The first line is wrong since flags
cannot be implicitly converted to unsigned long long
.
Given the definition of Flags
, the only legal C++ method to initialize iflags
is to use:
unsigned long long iflags = static_cast<unsigned int>(flags);
If you remove the explicit
qualifier from the conversion operator
class Flags {
unsigned int v;
public:
operator unsigned int() { return v; }
}
then you can use
unsigned long long iflags = static_cast<unsigned long long>(flags);
Upvotes: 1
Reputation: 137320
That static_cast
attempt falls under [expr.static.cast]/4, which roughly says that you can do static_cast<T>(e)
if you can do T t(e);
for some invented variable t
(there's some fun dance in the wording to take care of guaranteed elision and C-style cast oddities, which we can ignore for our purposes).
That initialization is controlled by [dcl.init]/17.7, which says you do overload resolution on the conversion functions of Flags
, with a pointer to [over.match.conv], which has this to say about candidates:
Those non-explicit conversion functions that are not hidden within [
Flags
] and yield type [unsigned long long
] or a type that can be converted to type [unsigned long long
] via a standard conversion sequence are candidate functions. For direct-initialization, those explicit conversion functions that are not hidden within [Flags
] and yield type [unsigned long long
] or a type that can be converted to type [unsigned long long
] with a qualification conversion are also candidate functions.
Your explicit operator unsigned int()
neither yields unsigned long long
nor a type that can be converted to it via a qualification conversion (which is irrelevant here - that conversion only applies to pointer-y things); it is therefore not a candidate. Since the candidate set is empty, overload resolution fails, so the initialization is ill-formed, and so is the static_cast
.
Upvotes: 1