Merrill Cornish
Merrill Cornish

Reputation: 89

Boost Variant: Is there magic in the binding order?

I have been reading everything I can find about Boost Variant. (I have a headache.) Some people were surprised that assigning a string literal got saved as a bool. If I listed char* before bool (after?) would a string literal get saved as a char* string? Does the ordering between v1 and v2 matter here?

boost::variant<char*, bool> v1 = "hello";
boost::variant<bool, char*> v2 = "hello";

For integers, should I simply bind the largest integer for all integers or should I individually bind int8_t thru int64_t? If I have them all bound then input one, which would fit in any of them, does it get saved as the first (last?) one?

How about float vs double?

Upvotes: 1

Views: 338

Answers (1)

sehe
sehe

Reputation: 393547

There's no magic.

There's just the documented behaviour of the constructor.

template<typename T> variant(T & operand);

Requires: T must be unambiguously convertible to one of the bounded types (i.e., T1, T2, etc.).

Postconditions: Content of *this is the best conversion of operand to one of the bounded types, as determined by standard overload resolution rules.

Throws: May fail with any exceptions arising from the conversion of operand to one of the bounded types.

Because both cases involve implicit conversions, it can happen that an unexpected element type is constructed.

See the below example

Live On Coliru

#include <boost/variant.hpp>

int main() {
    {
        boost::variant<bool, std::string> v;
        v = "hello"; // is char const(&)[6], converts to bool

        assert(0 == v.which());

        v = static_cast<char const*>("hello");
        assert(0 == v.which());
    }

    // compare to
    {
        boost::variant<bool, char const*> v;
        v = "hello"; // is char const(&)[6]

        assert(1 == v.which()); // now selects the direct match

        v = static_cast<char const*>("hello");
        assert(1 == v.which());
    }
}

Upvotes: 2

Related Questions