2

I'm having trouble with boost::variant (using boost 1.67.0).

When my template parameter list includes both bool and std::string, any variant objects which should be treated as string, seem to be implicitly bound to bool instead. For example:

using Varval = boost::variant<bool, std::string>;

void main()
{
    std::vector<Varval> vect{ true, false, "Hello_World" };

    std::cout << "[ ";
    for (const auto &v : vect)
        std::cout << v << "  ";
    std::cout << "]\n";
}

Outputs:

[ 1 0 1 ]

whereas if I change nothing but the first template argument, from bool to int, it works fine:

using Varval = boost::variant<int, std::string>;

void main()
{
    std::vector<Varval> vect{ true, false, "Hello_World" };

    std::cout << "[ ";
    for (const auto &v : vect)
        std::cout << v << "  ";
    std::cout << "]\n";
}

Properly outputs:

[ 1 0 Hello_World ]

Any ideas?

Blair Fonville
  • 908
  • 1
  • 11
  • 23

1 Answers1

3

boost::variant has one constructor overload for each stated type. In your first example there will be one overload for bool and one for std::string. You are now calling the constructor with a char[n] which can be imlicitly converted to both of them. So there is no perfect match but two candidates. But instead of telling you that the call is ambiguous, the compiler will choose the bool overload as the better match.

Why? That is already perfectly answered in this question.

In your second example with int and std::string you are passing bools and char[n] to the constructors. bool is implicitly convertable to int but not to std::string. char[n] is implicitly convertable to std::string but not to int. So the according constructors are called as there is only one candidate for each.

sebrockm
  • 5,733
  • 2
  • 16
  • 39