boost :: variant隐式强制转换为字符串

时间:2015-06-23 16:38:38

标签: c++ implicit-conversion boost-variant

我有一个不同类型的boost :: variant,其中一个是(const)void指针,另一个是字符串。

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

问题是,如果我想将它与c-string一起使用,则将其转换为void指针而不是字符串。

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

如果我删除了指针的常量,它会将它转换为字符串。

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

是否有一种简单的方法可以使boost :: variant隐式地将c-string转换为std :: string?

更新

我知道我可以明确表示:

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

但我想避免明确的施法。

4 个答案:

答案 0 :(得分:3)

您可以通过继承boost::variant来提供自己的变体模板。 通过重载const char*来实现从std::stringoperator=的正确转换:

#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;
}

输出&#34; 0&#34;根据需要。

实例:https://ideone.com/ZppUla

通过使用指定类型映射的traits类,可以更加概括这个想法:

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;

实例:https://ideone.com/AXUqTv

答案 1 :(得分:1)

根据我的知识,没有办法直接这样做,但你可以用包装器来解决它。基本的(根据你的需要进行修饰,并根据你的需要进行概括):

struct VariantWrapper
{
    template <class T>
    VariantWrapper& operator=(const T& val)
    {
        var = val;
        return *this;
    }

    template <int N>
    VariantWrapper& operator=(const char(&str)[N])
    {
        var = std::string(str);
        return *this;
    }

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

VariantWrapper bar;
bar = "foo";
std::cout << bar.var.which();

以上述方式执行此操作会将模板匹配限制为只是文字字符串和字符数组,但仍允许您使用const char*执行不同的操作。如果你想匹配适合c-string类别的所有内容,你可以使用const char*

答案 2 :(得分:0)

您可以从boost::variant<std::string, void const*>派生自己的类,并提供隐式const char *和字符串构造函数。

答案 3 :(得分:0)

可以使用xnode(类似于boost::variant的类在某些方面解决它,在其他方面类似于boost::any):

using namespace std;
xnode value = xnode::value_of("bar");
cout << "type: " << value.type().name() << ", value: " << value.get_as<string>() << endl;

此类中有明确的转换路径,用于字符串文字(数组)。

请参阅:https://github.com/vpiotr/xnode