我正在尝试编译以下源代码
#include <boost/property_tree/ptree.hpp>
int main() {
boost::property_tree::ptree b;
b.push_back(std::make_pair("a", "b"));
return 9;
}
使用以下编译器和说明:
$ g++ ./source.cpp --std=c++11
$ g++ --version
g++ (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ # boost version is 1.55
我收到以下错误
./source.cpp: In function ‘int main()’:
./source.cpp:5:41: error: no matching function for call to ‘boost::property_tree::basic_ptree<std::basic_string<char>, std::basic_string<char> >::push_back(std::pair<const char*, const char*>)’
b.push_back(std::make_pair("a", "b"));
^
In file included from /opt/boost/boost_1_55_0/boost/property_tree/ptree.hpp:516:0,
from ./source.cpp:1:
/opt/boost/boost_1_55_0/boost/property_tree/detail/ptree_implementation.hpp:362:9: note: candidate: boost::property_tree::basic_ptree<Key, Data, KeyCompare>::iterator boost::property_tree::basic_ptree<Key, Data, KeyCompare>::push_back(const value_type&) [with Key = std::basic_string<char>; Data = std::basic_string<char>; KeyCompare = std::less<std::basic_string<char> >; boost::property_tree::basic_ptree<Key, Data, KeyCompare>::value_type = std::pair<const std::basic_string<char>, boost::property_tree::basic_ptree<std::basic_string<char>, std::basic_string<char> > >]
basic_ptree<K, D, C>::push_back(const value_type &value)
^
/opt/boost/boost_1_55_0/boost/property_tree/detail/ptree_implementation.hpp:362:9: note: no known conversion for argument 1 from ‘std::pair<const char*, const char*>’ to ‘const value_type& {aka const std::pair<const std::basic_string<char>, boost::property_tree::basic_ptree<std::basic_string<char>, std::basic_string<char> > >&}’
注意:如果我在没有--std = c ++ 11的情况下编译它,则错误消失
问题:如何使用c ++ 11标准或更高版本编译它?我找到了https://svn.boost.org/trac10/ticket/6785,但在boost-1.55中,它已经被修复了。提前谢谢你!
答案 0 :(得分:1)
是的。这里真正的变化是std::make_pair
。
C ++ 11改变了std::pair
转换规则,以及make_pair
便利功能,它已被移动感知。
Property Tree允许这样的构造:
ptree pt("data");
构造一个只包含值数据且没有子节点的树。但是,该对second
成员的间接转换并不适用于c ++ 11模式:
std::pair<std::string, ptree> v = std::make_pair("a", "b");
此行将在c ++ 03中编译,但不再在c ++ 11中编译
要查明它是否是libstdc ++或编译器错误,我将其分离到这个最小样本中:
#include <utility>
#include <string>
struct X {
X(std::string){}
};
int main() {
std::pair<std::string, X> v = std::make_pair("a", "b");
}
注意一个微妙的观点,即构造函数不像
explicit
构造函数那样ptree(data_type const&)
并不重要。所需的额外隐式转换char const(&)[] -> std::string
足以导致c ++ 11拒绝该调用。
这个compiles in c++03但是fails in c++11在GCC下使用libstdc ++。
即使使用clang agrees,也要检查libc++ instead of libstdc++。
我敢打赌,这是设计上的,可能是因为
std::make_pair
更精确并且意识到移动语义。
变通办法是多方面的。明确转换:
b.push_back(std::make_pair("a", ptree("b")));
使类型显式始终有用:
b.push_back(ptree::value_type {"a", "b"});
统一初始化删除了一些错误:
b.push_back({"a", ptree{"b"}});
为了完整性,非显式构造函数更灵活:
b.push_back({"a", {}});
或者您可以完全避开pair<>
(value_type
)界面:
b.add_child("a", ptree{"b"});
b.add_child("a", {}).put_value("b");
但真正的关键是值节点不能有孩子。为什么不将值?
b.add("a", "b");
这是我的推荐。我觉得
std::pair<>
是一个实现细节,仅对与其他通用代码进行互操作有用。这会伤害可读性。
所有的变通方法一起生活在一起 Live On Coliru
打印
<?xml version="1.0" encoding="utf-8"?>
<a>b</a>
<a>b</a>
<a>b</a>
<a/>
<a>b</a>
<a>b</a>
<a>b</a>