The SFINAE logic in the declarations of the comparison operator free functions for bsoncxx::types::value is overly greedy, such that it prevents users from declaring their own comparison operator overloads which name bsoncxx::types::value as a parameter. See below for the current declarations of these functions:
385 // sfinae in the bool return to avoid competing with the value == value 386 // operators 387 template <typename T> 388 using not_value = 389 typename std::enable_if<!std::is_same<typename std::remove_reference<T>::type, value>::value, 390 bool>::type; 391 392 // these all return bool 393 template <typename T> 394 BSONCXX_INLINE not_value<T> operator==(const value& lhs, T&& rhs) { 395 return lhs == value{std::forward<T>(rhs)}; 396 } 397 398 template <typename T> 399 BSONCXX_INLINE not_value<T> operator==(T&& lhs, const value& rhs) { 400 return value{std::forward<T>(lhs)} == rhs; 401 } 402 403 template <typename T> 404 BSONCXX_INLINE not_value<T> operator!=(const value& lhs, T&& rhs) { 405 return lhs != value{std::forward<T>(rhs)}; 406 } 407 408 template <typename T> 409 BSONCXX_INLINE not_value<T> operator!=(T&& lhs, const value& rhs) { 410 return value{std::forward<T>(lhs)} != rhs; 411 }
In addition to inconveniencing users, this prevents us from being able to use bsoncxx::types::value as an operand in "REQUIRE(x == y)" statements with our unit testing framework, since those macro expansions declare operator==() overloads with decltype(y) as a parameter type.