C++ 如何返回boost::varaint返回类型中包含的类型子集生成的boost::variant
我有4个功能:C++ 如何返回boost::varaint返回类型中包含的类型子集生成的boost::variant,c++,boost,variant,boost-variant,C++,Boost,Variant,Boost Variant,我有4个功能: boost::variant<type1,type2,type3>processFile(const char* file){ if(----expression that if true means I have to process as type 1----) return processType1(file); //this just returns type1 else if(----expression that
boost::variant<type1,type2,type3>processFile(const char* file){
if(----expression that if true means I have to process as type 1----)
return processType1(file); //this just returns type1
else if(----expression that if true means I have to process as either type 1 or type 2----)
return processType23(file); //this returns boost::variant<type2,type3>. This also calls 2 more processing functions depending on type.
}
boost::VariantProcess文件(const char*文件){
if(---表达式,if true表示我必须作为类型1进行处理--)
return processType1(file);//这只返回type1
else if(---表达式,if true表示我必须作为类型1或类型2进行处理--)
return processType23(file);//返回boost::variant。这还根据类型调用另外两个处理函数。
}
processType23获取一个脚本文件,该文件将确定返回哪种类型。我想在这个文件中保留类型的确定。但是,我无法返回boost::variant。我得到以下错误:
error: could not convert 'engine::fileManager::processLua(const char*)()' from 'boost::variant<engine::material, engine::shader>' to 'boost::variant<engine::material, engine::shader, unsigned int>'
错误:无法将'engine::fileManager::processLua(const char*)()'从'boost::variant'转换为'boost::variant'
返回数据的(正确)方式是什么?您应该使用访问者:
template <typename R, typename A> convert_variant(A const& arg) {
return boost::apply_visitor([](auto const& v) -> R { return R{v}; }, arg);
}
#include <boost/variant.hpp>
#include <boost/type_traits.hpp>
#include <iostream>
template <typename R>
struct convert_variant_visitor : boost::static_visitor<R> {
struct bad_conversion : std::runtime_error {
bad_conversion(std::string msg) : std::runtime_error(msg) {}
};
template <typename T>
typename boost::enable_if_c<boost::is_convertible<T, R>::value, R>::type
operator()(T const& v) const
{
return R(v); // or just v
}
template <typename T>
typename boost::enable_if_c<not boost::is_convertible<T, R>::value, R>::type
operator()(T const& v) const
{
throw bad_conversion(std::string("Cannot convert ") + typeid(v).name() + " to " + typeid(R).name());
//throw bad_conversion("Not convertible to variant");
}
};
template <typename R, typename A> R convert_variant(A const& arg) {
return boost::apply_visitor(convert_variant_visitor<R>(), arg);
}
int main() {
typedef boost::variant<std::string, int, double> V1;
typedef boost::variant<int, double> V2;
V1 input = 42;
V2 output = convert_variant<V2>(input);
std::cout << "input: " << input << " (which: " << input.which() << ")\n";
std::cout << "output: " << output << " (which: " << output.which() << ")\n";
}
template <typename R, typename A> R convert_variant(A const& arg) {
return boost::apply_visitor([](auto const& v) -> R {
if constexpr (std::is_convertible_v<decltype(v), R>)
return v;
else
throw std::runtime_error("bad conversion");
} , arg);
}
C++17演示
现代C++特性使通用代码变得更简单:
template <typename R, typename A> convert_variant(A const& arg) {
return boost::apply_visitor([](auto const& v) -> R { return R{v}; }, arg);
}
#include <boost/variant.hpp>
#include <boost/type_traits.hpp>
#include <iostream>
template <typename R>
struct convert_variant_visitor : boost::static_visitor<R> {
struct bad_conversion : std::runtime_error {
bad_conversion(std::string msg) : std::runtime_error(msg) {}
};
template <typename T>
typename boost::enable_if_c<boost::is_convertible<T, R>::value, R>::type
operator()(T const& v) const
{
return R(v); // or just v
}
template <typename T>
typename boost::enable_if_c<not boost::is_convertible<T, R>::value, R>::type
operator()(T const& v) const
{
throw bad_conversion(std::string("Cannot convert ") + typeid(v).name() + " to " + typeid(R).name());
//throw bad_conversion("Not convertible to variant");
}
};
template <typename R, typename A> R convert_variant(A const& arg) {
return boost::apply_visitor(convert_variant_visitor<R>(), arg);
}
int main() {
typedef boost::variant<std::string, int, double> V1;
typedef boost::variant<int, double> V2;
V1 input = 42;
V2 output = convert_variant<V2>(input);
std::cout << "input: " << input << " (which: " << input.which() << ")\n";
std::cout << "output: " << output << " (which: " << output.which() << ")\n";
}
template <typename R, typename A> R convert_variant(A const& arg) {
return boost::apply_visitor([](auto const& v) -> R {
if constexpr (std::is_convertible_v<decltype(v), R>)
return v;
else
throw std::runtime_error("bad conversion");
} , arg);
}
模板R转换变量(常量和参数){
返回提升::应用访问者([](自动常量&v)->R{
如果constexpr(标准::可转换)
返回v;
其他的
抛出std::runtime_错误(“错误转换”);
},arg);
}
非常好,但我认为(不幸的是失败了)更接近询问者想要的东西。@llonesmiz你当然是对的。让我来解决这个问题。20年后minutes@llonesmiz我只是更新了答案,这样非法转换就会变成运行时错误。这使得它在您强调的情况下也能工作:a只是为了说明这可以简单得多,尽管考虑到的层叠,如果实际工作,这应该不是问题。