Question

I have the following function

template <typename T, typename U>
const T* visitor_fct(U& operand)
{
  return (boost::get<T>(&operand));
}

When I do

 boost::variant<int, std::string> str = "string";
 std::cout << visitor_fct<std::string>(str) << std::endl;

I get the correct output

But when I change the declaration of str to :

boost::variant<int, std::string, bool> str = "toto";

I am always getting a nullptr;

Why ?

Was it helpful?

Solution

The reason is that a string literal (char*)converts to bool better than to std::string so your string literal doesn't initialize the string component of the variant, but rather than bool component (to true).

See the following which outputs bool 1:

#include <iostream>

void foo(bool b)
{
    std::cout << "bool " << b << std::endl;
}

void foo(std::string s)
{
    std::cout << "string " << s << std::endl;
}

int main()
{
    foo("Bar");
}

Initializing with std::string("toto") will solve your problem.

4.12/1 shows us the conversion in question:

A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a
prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false;
any other value is converted to true. A prvalue of type std::nullptr_t can be converted to a prvalue of
type bool; the resulting value is false.

[As noted also in the other answer] This implicit conversion takes precedence over the converting constructor of std::string and so is selected, causing the type used in the variant to be bool.

OTHER TIPS

What seems to be happening here is because there's a bool present in the boost::variant, the const char* you're passing is no longer used for the string but rather is converted to bool.

if you change this line:

boost::variant<int, std::string, bool> str = "toto";

to this:

boost::variant<int, std::string, bool> str = std::string("toto");

it will work.

Here's why the bool gets chosen over the string: implicit conversions happen between any types of pointer and bool, and conversions between built-in types are always preferred to user-defined conversions. And since std::string is a user defined type (standard mind you but still user defined) the bool wins over the string.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top