c++ - C++14 constexpr union conditional initialization in constructor -
i pick union member initialized in constructor based on argument. following example works:
struct { union { int i; float f; }; a(double d, bool isint) { if (isint) new(&i) int(d); else new(&f) float(d); } }; while i'm using int , float, goal work other more complex types (but still allowable in c++14 union), hence use of placement-new (and not assignment).
the problem constructor cannot constexpr placement-new not allowed in constexpr methods. there way around (other making isint argument part of formal type system)? type of conditional initalizer list work, i'm unaware of way it.
there trick. key pieces are:
- a defaulted copy or move constructor union copies object representation (and copies active member), , permitted in constant expression evaluation.
- you cannot change active union member in constant expression evaluation after initialization complete, can delegate constructor delay choice.
- if delegate copy or move constructor, can pass in object initialized right state , copy active member.
putting together, get:
template<typename t> struct tag {}; struct { union { int i; float f; }; constexpr a(tag<int>, double d) : i(d) {} constexpr a(tag<float>, double d) : f(d) {} constexpr a(double d, bool isint) : a(isint ? a(tag<int>(), d) : a(tag<float>(), d)) {} }; constexpr a(1.0, true); // ok, initializes 'i' constexpr b(5, false); // ok, initializes 'f' this accepted recent clang, gcc, , edg, , requires c++11 constexpr.
warning: gcc 5.1.0 had bug miscompiled above code (initializing a , b 0); bug not present in earlier or later versions of gcc.
Comments
Post a Comment