From 3fecc369bed1819b99fd6fb7a5b4f24b0318eec9 Mon Sep 17 00:00:00 2001 From: Jason Carey Date: Wed, 29 Apr 2015 17:11:16 -0400 Subject: [PATCH] CXX-588 Cannot use kvp() with a std::string param sub_document.append() specializations for std::string and stdx::string_view keyed tuples fail to forward for the various cv and ref qualified variants. To keep up the perfect forwarding, these functions need to take the key type as a template type parameter and SFINAE themselves to disambiguate. --- src/bsoncxx/builder/basic/sub_document.hpp | 25 ++++++++++++---------- src/bsoncxx/test/bson_builder.cpp | 23 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/bsoncxx/builder/basic/sub_document.hpp b/src/bsoncxx/builder/basic/sub_document.hpp index 8bedff11a4..a8d6fa76c6 100644 --- a/src/bsoncxx/builder/basic/sub_document.hpp +++ b/src/bsoncxx/builder/basic/sub_document.hpp @@ -34,6 +34,7 @@ void value_append(core* core, T&& t); /// Users should almost always construct a builder::basic::document instead. /// class BSONCXX_API sub_document { + public: BSONCXX_INLINE sub_document(core* core) : _core(core) { } @@ -51,31 +52,33 @@ class BSONCXX_API sub_document { /// /// Appends a basic::kvp where the key is a non-owning string view. /// - template + template BSONCXX_INLINE - void append(std::tuple&& t) { - _core->key_view(std::get<0>(t)); - impl::value_append(_core, std::forward(std::get<1>(t))); + typename std::enable_if::type, stdx::string_view>::value>::type + append(std::tuple&& t) { + _core->key_view(std::forward(std::get<0>(t))); + impl::value_append(_core, std::forward(std::get<1>(t))); } /// /// Appends a basic::kvp where the key is an owning STL string. /// - template + template BSONCXX_INLINE - void append(std::tuple&& t) { - _core->key_owned(std::get<0>(t)); - impl::value_append(_core, std::forward(std::get<1>(t))); + typename std::enable_if::type, std::string>::value>::type + append(std::tuple&& t) { + _core->key_owned(std::forward(std::get<0>(t))); + impl::value_append(_core, std::forward(std::get<1>(t))); } /// /// Appends a basic::kvp where the key is a string literal /// - template + template BSONCXX_INLINE - void append(std::tuple&& t) { + void append(std::tuple&& t) { _core->key_view(stdx::string_view{std::get<0>(t), n - 1}); - impl::value_append(_core, std::forward(std::get<1>(t))); + impl::value_append(_core, std::forward(std::get<1>(t))); } private: diff --git a/src/bsoncxx/test/bson_builder.cpp b/src/bsoncxx/test/bson_builder.cpp index a4eceaba38..80c0363d1c 100644 --- a/src/bsoncxx/test/bson_builder.cpp +++ b/src/bsoncxx/test/bson_builder.cpp @@ -682,6 +682,29 @@ TEST_CASE("basic document builder works", "[bsoncxx::builder::basic]") { viewable_eq_viewable(stream, basic); } + SECTION("kvp works with std::string key/value") { + { + using namespace builder::basic; + + std::string a("hello"); + std::string b("world"); + basic.append(kvp(a, b)); + } + + viewable_eq_viewable(stream, basic); + } + + SECTION("kvp works with stdx::string_view key/value") { + { + using namespace builder::basic; + + stdx::string_view a("hello"); + stdx::string_view b("world"); + basic.append(kvp(a, b)); + } + + viewable_eq_viewable(stream, basic); + } SECTION("variadic works") { { using namespace builder::stream;