diff --git a/include/boost/property_tree/ptree.hpp b/include/boost/property_tree/ptree.hpp index ac4593ba5..2743123c9 100644 --- a/include/boost/property_tree/ptree.hpp +++ b/include/boost/property_tree/ptree.hpp @@ -270,6 +270,10 @@ namespace boost { namespace property_tree const self_type &get_child(const path_type &path, const self_type &default_value) const; + /** Prevents calls to get_child with temporary default values */ + void get_child(const path_type &path, + const self_type &&default_value) const = delete; + /** Get the child at the given path, or return boost::null. */ optional get_child_optional(const path_type &path); diff --git a/test/test_property_tree.cpp b/test/test_property_tree.cpp index ba1b9fbe4..1038b87ff 100644 --- a/test/test_property_tree.cpp +++ b/test/test_property_tree.cpp @@ -9,6 +9,7 @@ // ---------------------------------------------------------------------------- #include "test_utils.hpp" #include +#include #include #include #include @@ -67,6 +68,11 @@ struct any_translator } }; +// Checks the validity of calling get_child with a default value type +template +using get_child_accepts_default_of_type = decltype( + std::declval

().get_child(std::declval(), std::declval())); + namespace boost { namespace property_tree { template struct translator_between diff --git a/test/test_property_tree.hpp b/test/test_property_tree.hpp index bd4a764b0..2f4ac50ab 100644 --- a/test/test_property_tree.hpp +++ b/test/test_property_tree.hpp @@ -820,14 +820,27 @@ void test_get_child_put_child(PTREE *) BOOST_TEST(cpt2.get_child(T("k2.k")) == pt); // Do correct extractions via get_child (default value version) - BOOST_TEST(pt1.get_child(T("k1"), PTREE(T("def"))) != PTREE(T("def"))); - BOOST_TEST(pt1.get_child(T("k2.k"), PTREE(T("def"))) != PTREE(T("def"))); - BOOST_TEST(pt2.get_child(T("k1"), PTREE(T("def"))) == pt); - BOOST_TEST(pt2.get_child(T("k2.k"), PTREE(T("def"))) == pt); - BOOST_TEST(cpt1.get_child(T("k1"), PTREE(T("def"))) != PTREE(T("def"))); - BOOST_TEST(cpt1.get_child(T("k2.k"), PTREE(T("def"))) != PTREE(T("def"))); - BOOST_TEST(cpt2.get_child(T("k1"), PTREE(T("def"))) == pt); - BOOST_TEST(cpt2.get_child(T("k2.k"), PTREE(T("def"))) == pt); + PTREE dflt(T("def")); + BOOST_TEST(pt1.get_child(T("k1"), dflt) != dflt); + BOOST_TEST(pt1.get_child(T("k2.k"), dflt) != dflt); + BOOST_TEST(pt2.get_child(T("k1"), dflt) == pt); + BOOST_TEST(pt2.get_child(T("k2.k"), dflt) == pt); + BOOST_TEST(cpt1.get_child(T("k1"), dflt) != dflt); + BOOST_TEST(cpt1.get_child(T("k2.k"), dflt) != dflt); + BOOST_TEST(cpt2.get_child(T("k1"), dflt) == pt); + BOOST_TEST(cpt2.get_child(T("k2.k"), dflt) == pt); + + // Ensure that get_child does not compile when using temporaries as the default value. + BOOST_TEST((!boost::mp11::mp_valid::value)); + BOOST_TEST((!boost::mp11::mp_valid::value)); + BOOST_TEST((!boost::mp11::mp_valid::value)); + BOOST_TEST((!boost::mp11::mp_valid::value)); + + // Test get_child_accepts_default_of_type itself + BOOST_TEST((boost::mp11::mp_valid::value)); + BOOST_TEST((boost::mp11::mp_valid::value)); + BOOST_TEST((boost::mp11::mp_valid::value)); + BOOST_TEST((boost::mp11::mp_valid::value)); // Do correct extractions via get_child (optional version) boost::optional opt;