Skip to content

Commit 050b881

Browse files
hanumantmkamidvidy
authored andcommitted
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. Closes #291, #281 Signed-off-by: Adam Midvidy <amidvidy@gmail.com>
1 parent c9f1ad1 commit 050b881

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

src/bsoncxx/builder/basic/sub_document.hpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ void value_append(core* core, T&& t);
3434
/// Users should almost always construct a builder::basic::document instead.
3535
///
3636
class BSONCXX_API sub_document {
37+
3738
public:
3839
BSONCXX_INLINE sub_document(core* core) : _core(core) {
3940
}
@@ -51,31 +52,33 @@ class BSONCXX_API sub_document {
5152
///
5253
/// Appends a basic::kvp where the key is a non-owning string view.
5354
///
54-
template <typename T>
55+
template <typename K, typename V>
5556
BSONCXX_INLINE
56-
void append(std::tuple<stdx::string_view, T>&& t) {
57-
_core->key_view(std::get<0>(t));
58-
impl::value_append(_core, std::forward<T>(std::get<1>(t)));
57+
typename std::enable_if<std::is_same<typename std::decay<K>::type, stdx::string_view>::value>::type
58+
append(std::tuple<K, V>&& t) {
59+
_core->key_view(std::forward<K>(std::get<0>(t)));
60+
impl::value_append(_core, std::forward<V>(std::get<1>(t)));
5961
}
6062

6163
///
6264
/// Appends a basic::kvp where the key is an owning STL string.
6365
///
64-
template <typename T>
66+
template <typename K, typename V>
6567
BSONCXX_INLINE
66-
void append(std::tuple<std::string, T>&& t) {
67-
_core->key_owned(std::get<0>(t));
68-
impl::value_append(_core, std::forward<T>(std::get<1>(t)));
68+
typename std::enable_if<std::is_same<typename std::decay<K>::type, std::string>::value>::type
69+
append(std::tuple<K, V>&& t) {
70+
_core->key_owned(std::forward<K>(std::get<0>(t)));
71+
impl::value_append(_core, std::forward<V>(std::get<1>(t)));
6972
}
7073

7174
///
7275
/// Appends a basic::kvp where the key is a string literal
7376
///
74-
template <std::size_t n, typename T>
77+
template <std::size_t n, typename V>
7578
BSONCXX_INLINE
76-
void append(std::tuple<const char (&)[n], T>&& t) {
79+
void append(std::tuple<const char (&)[n], V>&& t) {
7780
_core->key_view(stdx::string_view{std::get<0>(t), n - 1});
78-
impl::value_append(_core, std::forward<T>(std::get<1>(t)));
81+
impl::value_append(_core, std::forward<V>(std::get<1>(t)));
7982
}
8083

8184
private:

src/bsoncxx/test/bson_builder.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,29 @@ TEST_CASE("basic document builder works", "[bsoncxx::builder::basic]") {
682682
viewable_eq_viewable(stream, basic);
683683
}
684684

685+
SECTION("kvp works with std::string key/value") {
686+
{
687+
using namespace builder::basic;
688+
689+
std::string a("hello");
690+
std::string b("world");
691+
basic.append(kvp(a, b));
692+
}
693+
694+
viewable_eq_viewable(stream, basic);
695+
}
696+
697+
SECTION("kvp works with stdx::string_view key/value") {
698+
{
699+
using namespace builder::basic;
700+
701+
stdx::string_view a("hello");
702+
stdx::string_view b("world");
703+
basic.append(kvp(a, b));
704+
}
705+
706+
viewable_eq_viewable(stream, basic);
707+
}
685708
SECTION("variadic works") {
686709
{
687710
using namespace builder::stream;

0 commit comments

Comments
 (0)