-
Notifications
You must be signed in to change notification settings - Fork 543
[CXX-2625] More type traits + invoke() #1042
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CXX-2625] More type traits + invoke() #1042
Conversation
Some type traits in this PR uses alias templates, e.g.: template <typename Type, typename... Traits>
using requires_t = enable_if_t<conjunction<Traits...>::value, Type>; Additionally, some constraints are expressed as return types (the traditional template <typename T>
bsoncxx::stdx::requires_t<void, bsoncxx::stdx::is_alike<T, int>> //
only_int(T) {} // Example A Instead, I suggest (1) going all-in on defining type traits using named structs whenever possible (including the implementation of template <typename Type, typename... Traits>
struct requires : std::enable_if<conjunction<Traits...>::value, Type> {};
template <typename Type, typename... Traits>
using requires_t = typename requires<Type, Traits...>::type; And (2) moving the constraints into the template parameter list instead of the return type (as is already being done for some ctors, e.g. template <typename T, bsoncxx::stdx::requires_t<void, bsoncxx::stdx::is_alike<T, int>>* = nullptr>
void only_int(T) {} // Example B Both suggestions are to improve the quality of error messages. The currently proposed changes emit the following error message on constraint failure for the
Suggestion 1 ensures the named type trait is embedded in the error message, rather than its obscure substituted implementation details (suggestion applied to both
Suggestion 2 avoids the noisy mess that obscures the return type in the function declaration (+ the noisy repetition of the constraint when the return type happens to be on the same line as the function name), while still preserving clean SFINAE semantics that is consistent across all functions (including ctors), and also being friendlier to ClangFormat even for complex constraints (no
Additionally, a suggestion 3: despite the convenience of template <typename T,
bsoncxx::stdx::requires_t<void,
bsoncxx::stdx::is_alike<T, double>,
bsoncxx::stdx::is_alike<T, int>>* = nullptr>
void impossible(T) {} The error message looks as follows (the entire constraint is emitted as-is):
Whereas if using explicit template <typename T,
typename std::enable_if<bsoncxx::stdx::is_alike<T, double>::value &&
bsoncxx::stdx::is_alike<T, int>::value>::type* = nullptr>
void impossible(T) {} The error message looks as follows (more meaningful and specific reason for constraint failure):
|
src/bsoncxx/test/CMakeLists.txt
Outdated
@@ -22,6 +22,7 @@ else() | |||
bsoncxx_add_library(bsoncxx_testing "bsoncxx-testing" STATIC) | |||
endif() | |||
|
|||
file(GLOB src_bsoncxx_test_DIST_cpps CONFIGURE_DEPENDS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unused src_bsoncxx_test_DIST_cpps
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not yet addressed.
src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/type_traits.hpp
Outdated
Show resolved
Hide resolved
src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/type_traits.hpp
Outdated
Show resolved
Hide resolved
src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/types/bson_value/view.hpp
Outdated
Show resolved
Hide resolved
requires_t for more constraint visibility
@eramongodb The avoidance of instantiating class templates is intentional since it explodes can explode compilation time. I was also unsatisfied with the opaque diagnostic messages on constraint failure, so I've added some changes that will produce better error messages on almost all compilers, and often better than the compilers' special-cases for enable_if. Most oddities in the placement of the SFINAE constraints are specifically to appease VS2015, which has horribly broken SFINAE behavior. When we drop VS2015 support, we will be safe to relocate the constraints to the template parameter lists in (almost?) all contexts (without needing to add the |
src/bsoncxx/test/CMakeLists.txt
Outdated
@@ -22,6 +22,7 @@ else() | |||
bsoncxx_add_library(bsoncxx_testing "bsoncxx-testing" STATIC) | |||
endif() | |||
|
|||
file(GLOB src_bsoncxx_test_DIST_cpps CONFIGURE_DEPENDS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not yet addressed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find it difficult to review what traits are implemented in such a manner to avoid VS 2015 compatibility issues vs. what are not, but the intent/context is understood.
src/bsoncxx/include/bsoncxx/v_noabi/bsoncxx/stdx/type_traits.hpp
Outdated
Show resolved
Hide resolved
@@ -84,8 +86,7 @@ class BSONCXX_API value { | |||
/// @param t | |||
/// A user-defined object to serialize into a BSON object. | |||
/// | |||
template <typename T, | |||
typename std::enable_if<!std::is_same<T, typename array::view>::value, int>::type = 0> | |||
template <typename T, _traits::requires_not_t<int, std::is_same<T, array::view>> = 0> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concern: unlike all other functions in this PR that use SFINAE, this ctor is not declared with BSONCXX_INLINE
or BSONCXX_PRIVATE
despite being a member of a BSONCXX_API
-declared class, meaning instantiations are part of the public ABI. Although this does not yet pose an issue (given it's still a member of the unstable ABI namespace), this might be something we want to address before/during its migration into the stable ABI namespace.
Side-note: we may want to establish a style/coding guideline for the CXX Driver libraries that ABI-stability of template instantiations are not supported even for members of the stable ABI namespace (or classes in that namespace) to avoid the complexity of maintaining ABI-stability of symbols that depend on our traits/SFINAE utilities.
|
||
namespace bsoncxx { | ||
|
||
BSONCXX_INLINE_NAMESPACE_BEGIN |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BSONCXX_INLINE_NAMESPACE_BEGIN | |
inline namespace v_noabi { |
Consistency with changes in #1039.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could that macro be removed completely, or is it too much part of the public API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was considered, but I think it's been part of the API for too long to risk its sudden removal. I intend to document them as deprecated as part of CXX-2745 work.
(CXX-2625) This changeset adds many additional type traits from C++14 and beyond, especially for easier "SFINAE trickery". Many are C++14/17 traits, some are from library fundamentals, and some are neither.
This changeset does not fully replace any existing dependencies, but will make it easier to do so going forward, as well as cleaning up some of our own metaprogramming trickery.