C++ 通过boost的递归对。自boost 1.62以来的变量已中断
我正在处理的代码使用递归对。在简化的示例中,该类型包含一个由C++ 通过boost的递归对。自boost 1.62以来的变量已中断,c++,boost,boost-variant,C++,Boost,Boost Variant,我正在处理的代码使用递归对。在简化的示例中,该类型包含一个由字符串和int或另一个这样的对组成的对。这应该(并且是)通过以下方式实现: #include <boost/variant.hpp> #include <string> using namespace std; typedef boost::make_recursive_variant < std::pair < std::string , boost:
字符串
和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));
}
这只适用于一种类型。其他人也同样失败
有人知道为什么这不再有效,以及如何修复吗?我认为您实际上遇到了类似于
std::pair
的更改,如图所示:
自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::pair
隐式转换为std::pair
,而且还希望使用该转换的结果作为所分配变量的初始值设定项
在C++的所有部分中,这要求两个隐式转换,编译器永远无法解决使用它的过载。
所以,实际上您的代码有点草率,因为它使用了Boost变体可能不具备的“回旋余地”。这是一个突破性的变化,但新的行为似乎更有意义 另一个音符 您正在使用单个元素创建递归变量。那是。。。有点奇怪 通过将std::pair
结构属性隐藏在variant
的第一层下,这会使类型系统“紧张”一点
直接使用std::pair
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 << "\n";
std::cout << "yyy:" << yyy << "\n";
std::cout << "zzz:" << zzz << "\n";
std::cout << "huh:" << huh << "\n";
std::cout << "simple:" << simple << "\n";
}
我能想象的最无聊的事情是:
#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);
}
但是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 << "\n";
std::cout << "yyy:" << yyy << "\n";
std::cout << "zzz:" << zzz << "\n";
std::cout << "huh:" << huh << "\n";
std::cout << "simple:" << simple << "\n";
}
有一个更好的(不是那么“无聊”的解决方案,重复性更少:我在评估你的解决方案并将其应用于“真实事物”时发现了这一点。在我接受你的回答之前,这只是基于“我想要什么?”(因此评论):你的第一个变体在叮当声上失败了:此外,我更喜欢它,因为它在真实事物上的重复更少。虽然你的“ctor帮助”看起来不错,但我希望它不是必需的。哦,这似乎是Clang3.8中的一个bug,在Clang3.9中得到了解决:Boost变体的更改列在发行说明中
xxx:{s,0}
yyy:{s,5}
zzz:0
huh:{s,{more,{intricate,{nested,{truths,42}}}}}
simple:{not_so_simple,{simple,5}}