Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost::variant implicit cast to string

I have a boost::variant with different types, where one is a (const) void pointer and another a string.

boost::variant<std::string, void const*>;

The problem is, if i want to use it with a c-string it casts it to the void pointer instead the string.

boost::variant<std::string, void const*> foo;
foo = "bar";
std::cout << foo.which(); // prints 1 -> void const*

If I remove the constness of the pointer it will cast it to the string.

boost::variant<std::string, void*> foo; // no const pointer
foo = "bar";
std::cout << foo.which(); // prints 0 -> string

Is there an easy way to make boost::variant implicitly cast the c-string to a std::string?

UPDATE

I know I can cast explicit with:

foo = std::string("bar");

But I would like to avoid the explicit casting.

like image 303
user1810087 Avatar asked Jul 04 '26 06:07

user1810087


1 Answers

You can provide your own variant template by inheriting from boost::variant. The correct conversion from const char* to std::string is achieved through overloading the operator=:

#include <iostream>
#include <string>
#include <boost/variant.hpp>

template <typename... Types>
struct my_variant : public boost::variant<Types...>
{
    using boost::variant<Types...>::variant;

    auto operator=(const char* rhs)
    {
        return boost::variant<Types...>::operator=(std::string(rhs));
    }
};

int main() 
{
    my_variant<std::string, void const*> foo;
    foo = "bar";
    std::cout << foo.which(); 
    return 0;
}

Outputs "0" as desired.

Live example: https://ideone.com/ZppUla

This idea could be even more generalized through the use of a traits class which specifies the type mapping:

template <template <typename> class conv_traits, typename... Types>
struct my_variant : public boost::variant<Types...>
{
    using boost::variant<Types...>::variant;

    template <typename T>
    auto operator=(T rhs)
    {
        return boost::variant<Types...>::operator=(static_cast<typename conv_traits<T>::type>(rhs));
    }
};

template <typename T>
struct conversion_traits
{
    typedef T type;
};

template <>
struct conversion_traits<const char*>
{
    typedef std::string type;
};

my_variant<conversion_traits, std::string, void const*> foo;

Live example: https://ideone.com/AXUqTv

like image 164
m.s. Avatar answered Jul 05 '26 22:07

m.s.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!