通过boost.Variant递归对,因为提升1.62
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过boost.Variant递归对,因为提升1.62相关的知识,希望对你有一定的参考价值。
我正在处理的代码使用递归对。在简化示例中,类型包含由string
和int
或另一个这样的对组成的对。这应该(并且可以)实现:
#include <boost/variant.hpp>
#include <string>
using namespace std;
typedef boost::make_recursive_variant
< std::pair
< std::string
, boost::variant<int, boost::recursive_variant_>
>
>::type recursivePair;
typedef boost::variant< int
, recursivePair
> intPairVariant;
using sType = boost::variant<pair<string, string>, int>;
void foo(){
sType bar(make_pair("aa", "bb"));
recursivePair xxx(std::make_pair (std::string("s"), intPairVariant()));
recursivePair yyy(std::make_pair (string("s"), 5));
recursivePair zzz(std::make_pair ("s", 5));
}
sType
表明该对中的隐含转换仍然适用。
但是从Boost 1.62开始,这会在编译期间中断:
error: no matching function for call to ‘boost::variant<boost::detail::variant::recursive_flag<std::pair<std::__cxx11::basic_string<char>, boost::variant<int, boost::recursive_variant_> > > >::variant(std::pair<std::__cxx11::basic_string<char>, int>)’
recursivePair yyy(std::make_pair (string("s"), 5));
这仅适用于一种类型。其他人也失败了。
有谁知道为什么这不再起作用以及如何解决这个问题?
我认为你实际上遇到了类似于std::pair<>
的变化:does boost-1.55 boost::property_tree::ptree compile with c++11?
自c ++ 11以来,std :: pair的隐式转换次数较少。确实,你的代码确实编译了boost <1.62,但实质上看起来这是一个错误,至少在c ++ 11模式下。
在C ++ 11中,您这样做:
std::make_pair(s, i); // s is std::string, i is int
这导致std::pair<std::string, int>
。接下来,您不仅要求将std::pair<std::string, int>
隐式转换为std::pair<std::string, IntPairVariant>
,而且您希望将该转换的结果用作您指定的变体的初始值设定项。
在C ++的所有部分中,都要求进行两次隐式转换,编译器永远不会使用它来解决重载问题。
所以,实际上你的代码有点草率,因为它使用了Boost Variant应该没有的“余地”。这是一个突破性的变化,但新的行为似乎更有意义。
另一个说明
您正在使用单个元素创建递归变体。那......有点奇怪。
通过将std::pair<>
结构属性隐藏在variant
的第一层之下,这使得类型系统“紧张”了一点点。
直接使用A std::pair
我能想象的最无聊的事情:
#include <boost/variant.hpp>
#include <string>
using namespace std;
typedef std::pair<std::string,
boost::make_recursive_variant<int, std::pair<std::string, boost::recursive_variant_> >::type >
recursivePair;
typedef boost::variant<int, recursivePair> intPairVariant;
int main() {
recursivePair xxx(std::string("s"), intPairVariant());
recursivePair yyy(string("s"), 5);
recursivePair zzz("s", 5);
}
请注意,这已经允许您的问题中的确切拼写:
recursivePair xxx(std::make_pair(std::string("s"), intPairVariant()));
recursivePair yyy(std::make_pair(string("s"), 5));
recursivePair zzz(std::make_pair("s", 5));
但make_pair
在所有三种情况下都是多余的。
有趣的变化
也许你可以做更多的事情
struct V;
using Pair = std::pair<std::string, V>;
struct V : boost::variant<int, boost::recursive_wrapper<Pair> > {
using base = boost::variant<int, boost::recursive_wrapper<Pair> >;
using base::base;
using base::operator=;
};
现在你可以放心地说
Pair xxx("s", V{});
Pair yyy("s", 5);
Pair zzz{};
帮助构造函数
使用派生结构而不是普通变体的好处是,您实际上可以消除构造函数的歧义:
#include <boost/variant.hpp>
#include <string>
#include <iostream>
namespace mylib {
struct V;
using Pair = std::pair<std::string, V>;
struct V : boost::variant<int, boost::recursive_wrapper<Pair> > {
using base = boost::variant<int, boost::recursive_wrapper<Pair> >;
V() = default;
V(V&&) = default;
V(V const&) = default;
V& operator=(V&&) = default;
V& operator=(V const&) = default;
V(int i) : base(i) {}
V(std::string const& key, V value);
};
V::V(std::string const& key, V value) : base{Pair{std::move(key), std::move(value)}} {}
static inline std::ostream& operator<<(std::ostream& os, Pair const& p) {
return os << "{" << p.first << "," << p.second << "}";
}
}
int main() {
using mylib::V;
V xxx("s", mylib::V{});
V yyy("s", 5);
V zzz{};
V huh("s", {"more", {"intricate", {"nested", { "truths", 42} } } });
V simple = 5;
simple = {"simple", 5};
simple = {"not_so_simple", simple};
std::cout << "xxx:" << xxx << "
";
std::cout << "yyy:" << yyy << "
";
std::cout << "zzz:" << zzz << "
";
std::cout << "huh:" << huh << "
";
std::cout << "simple:" << simple << "
";
}
打印
xxx:{s,0}
yyy:{s,5}
zzz:0
huh:{s,{more,{intricate,{nested,{truths,42}}}}}
simple:{not_so_simple,{simple,5}}
以上是关于通过boost.Variant递归对,因为提升1.62的主要内容,如果未能解决你的问题,请参考以下文章
Boost::Variant 和其中的 function_types:如何将函数放入 Boost::variant?