в с ++ 11

аюсь скомпилировать следующий исходный код

#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)

std::make_pair.

C ++ 11 измененstd::pair правила конвертации, а такжеmake_pair удобная функция, которая была сделана с учетом движения.

Анализируя это

Дерево свойств позволяет строить так:

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 отклонил вызов.

Этоткомпилируется в c ++ 03 нотерпит неудачу в C ++ 11 под GCC с libstdc ++.

Просто чтобы проверить,лязг соглашается даже при использованииlibc ++ вместо 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 Demo

Все обходные пути счастливо жить вместеЖить на Колиру

Печать

<?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>
 sehe10 нояб. 2017 г., 11:23
Если у вас есть время для отличного разговора, послушайте, как Стефан Лававей объясняет, почемуstd::make_pair<std::string, ptree> являетсяне решение, которое вы хотите сделать«Не помогай компилятору» 48:42, Он также объясняет некоторые измененияstd::pair а такжеstd::make_pair в с ++ 11

Ваш ответ на вопрос