boost::variant 隐式转换为字符串
boost::variant implicit cast to string
我有一个具有不同类型的 boost::variant,其中一个是 (const) void 指针,另一个是字符串。
boost::variant<std::string, void const*>;
问题是,如果我想将它与 c 字符串一起使用,它会将它转换为 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 字符串隐式转换为 std::string?
更新
我知道我可以显式转换为:
foo = std::string("bar");
但我想避免显式转换。
您可以从 boost::variant<std::string, void const*>
派生您自己的 class 并提供隐式 const char* 和字符串构造函数。
据我所知,没有办法直接执行此操作,但您可以使用包装器解决它。基础款(随意修饰,随意泛化):
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 字符串类别的东西,你可以只使用 const char*
。
您可以通过继承 boost::variant
来提供自己的变体模板。
从 const char*
到 std::string
的正确转换是通过重载 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;
}
根据需要输出“0”。
这个想法可以通过使用指定类型映射的特征 class 来更普遍化:
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;
可以用xnode
来解决(class在某些方面类似于boost::variant
,在其他方面类似于boost::any
):
using namespace std;
xnode value = xnode::value_of("bar");
cout << "type: " << value.type().name() << ", value: " << value.get_as<string>() << endl;
此 class 中有针对字符串文字(数组)的显式转换路径。
我有一个具有不同类型的 boost::variant,其中一个是 (const) void 指针,另一个是字符串。
boost::variant<std::string, void const*>;
问题是,如果我想将它与 c 字符串一起使用,它会将它转换为 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 字符串隐式转换为 std::string?
更新
我知道我可以显式转换为:
foo = std::string("bar");
但我想避免显式转换。
您可以从 boost::variant<std::string, void const*>
派生您自己的 class 并提供隐式 const char* 和字符串构造函数。
据我所知,没有办法直接执行此操作,但您可以使用包装器解决它。基础款(随意修饰,随意泛化):
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 字符串类别的东西,你可以只使用 const char*
。
您可以通过继承 boost::variant
来提供自己的变体模板。
从 const char*
到 std::string
的正确转换是通过重载 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;
}
根据需要输出“0”。
这个想法可以通过使用指定类型映射的特征 class 来更普遍化:
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;
可以用xnode
来解决(class在某些方面类似于boost::variant
,在其他方面类似于boost::any
):
using namespace std;
xnode value = xnode::value_of("bar");
cout << "type: " << value.type().name() << ", value: " << value.get_as<string>() << endl;
此 class 中有针对字符串文字(数组)的显式转换路径。