使用c ++ 11进行boost-1.55 boost :: property_tree :: ptree编译吗?

时间:2017-11-09 23:27:32

标签: c++11 boost

我正在尝试编译以下源代码

#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中,它已经被修复了。提前谢谢你!

1 个答案:

答案 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>