From c104e28ebfdb4cbb37c550b507d12df2dc16d750 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 5 Jan 2016 20:53:31 +0100 Subject: [PATCH] inline(#985): provide our own minimal variant of enable_if this is a stripped-down and very leightweight variant of the well-known enable_if metaprogramming trick. Providing this standard variant in a header with minimal dependencies will allow us to phase out boost inclusions from many further headers. As a plus, our own variant is written such as to be more conciese in usage (no "typename" and no acces of an embedded "::type" menber) --- research/try.cpp | 17 +--- src/lib/meta/util.hpp | 38 ++++++++- src/lib/meta/virtual-copy-support.hpp | 88 +++++++++++---------- tests/library/meta/tuple-diagnostics.hpp | 16 ++-- tests/library/meta/typelist-diagnostics.hpp | 6 +- 5 files changed, 94 insertions(+), 71 deletions(-) diff --git a/research/try.cpp b/research/try.cpp index 252532b1c..13878cc46 100644 --- a/research/try.cpp +++ b/research/try.cpp @@ -80,6 +80,7 @@ typedef unsigned int uint; using lib::diff::GenNode; using lib::P; +using lib::meta::enable_if; using lib::meta::can_convertToString; using std::string; @@ -90,22 +91,6 @@ using std::endl; -/////////////////////////////////////////planned for meta/util.hpp - template - struct enable_if_c { - typedef T type; - }; - - template - struct enable_if_c {}; - - template - using enable_if = typename enable_if_c::type; - - template - using disable_if = typename enable_if_c::type; - -/////////////////////////////////////////planned for meta/util.hpp ///////////////////////////////copied from format-util.hpp diff --git a/src/lib/meta/util.hpp b/src/lib/meta/util.hpp index 4988b7600..073a9f5fb 100644 --- a/src/lib/meta/util.hpp +++ b/src/lib/meta/util.hpp @@ -59,6 +59,43 @@ namespace std { // forward declaration for std::string... namespace lib { namespace meta { + /* === conditional definition selector === */ + + template + struct enable_if_c { + typedef T type; + }; + + template + struct enable_if_c {}; + + + /** SFINAE helper to control the visibility of specialisations and overloads. + * \par explanation + * This template needs to be interspersed somehow into a type expression, which + * is driven by an external, primary type parameter. Thus, it is possible to use + * it on an extraneous, possibly default template parameter, or when forming the + * return type of a function. The purpose is to remove a given definition from + * sight, unless a boolean condition `Cond::value` holds true. In the typical + * usage, this condition is suppled by a _metafunction_, i.e. a template, which + * detects some feature or other circumstantial condition with the types involved. + * @remarks this is a widely used facility, available both from boost and from + * the standard library. For the most common case, we roll our own + * variant here, which is slightly stripped down and a tiny bit + * more concise than the boost variant. This way, we can avoid + * a lot of boost inclusions, which always bear some weight. + * @see [std::enable_if](http://en.cppreference.com/w/cpp/types/enable_if) + */ + template + using enable_if = typename enable_if_c::type; + + template + using disable_if = typename enable_if_c::type; + + + + + /* === building metafunctions === */ /** helper types to detect the overload resolution chosen by the compiler */ @@ -68,7 +105,6 @@ namespace meta { - /** detect possibility of a conversion to string. * Naive implementation just trying the direct conversion. * The embedded constant #value will be true in case this succeeds. diff --git a/src/lib/meta/virtual-copy-support.hpp b/src/lib/meta/virtual-copy-support.hpp index 0fea250de..dc9be739b 100644 --- a/src/lib/meta/virtual-copy-support.hpp +++ b/src/lib/meta/virtual-copy-support.hpp @@ -130,7 +130,8 @@ namespace meta{ using std::is_move_constructible; using std::is_copy_constructible; using std::is_copy_assignable; - using std::enable_if; + using std::__and_; + using std::__not_; namespace error = lumiera::error; @@ -239,44 +240,47 @@ namespace meta{ - /** workaround for GCC 4.7: need to exclude some types, - * since they raise private access violation during probing. - * Actually, in C++11 such a case should trigger substitution - * failure, not an compilation error */ - template - struct can_use_assignment - : is_copy_assignable - { }; - - template<> - struct can_use_assignment - { static constexpr bool value = false; }; - - - - template - struct use_if_supports_only_move - : enable_if< is_move_constructible::value - && !is_copy_constructible::value - && !can_use_assignment::value - > - { }; - - template - struct use_if_supports_cloning - : enable_if< is_move_constructible::value - && is_copy_constructible::value - && !can_use_assignment::value - > - { }; - - template - struct use_if_supports_copy_and_assignment - : enable_if< is_move_constructible::value - && is_copy_constructible::value - && can_use_assignment::value - > - { }; + namespace { // helpers to select suitable variant of copy support... + + /** workaround for GCC 4.7: need to exclude some types, + * since they raise private access violation during probing. + * Actually, in C++11 such a case should trigger substitution + * failure, not an compilation error */ + template + struct can_use_assignment + : is_copy_assignable + { }; + + template<> + struct can_use_assignment + { static constexpr bool value = false; }; + + + + template + struct supports_only_move + : __and_ + ,__not_> + ,__not_> + > + { }; + + template + struct supports_cloning + : __and_ + ,is_copy_constructible + ,__not_> + > + { }; + + template + struct supports_copy_and_assignment + : __and_ + ,is_copy_constructible + ,can_use_assignment + > + { }; + } @@ -292,21 +296,21 @@ namespace meta{ }; template - struct CopySupport::type> + struct CopySupport> > { template using Policy = MoveSupport; }; template - struct CopySupport::type> + struct CopySupport> > { template using Policy = CloneSupport; }; template - struct CopySupport::type> + struct CopySupport> > { template using Policy = FullCopySupport; diff --git a/tests/library/meta/tuple-diagnostics.hpp b/tests/library/meta/tuple-diagnostics.hpp index c541a96bf..16a3217d8 100644 --- a/tests/library/meta/tuple-diagnostics.hpp +++ b/tests/library/meta/tuple-diagnostics.hpp @@ -139,8 +139,8 @@ namespace test { /* ===== printing Tuple types and contents ===== */ template - typename enable_if< is_TuplePlain >, - string >::type + enable_if< is_TuplePlain>, + string > showDump (Tuple const& tuple) { typedef BuildTupleAccessor BuildAccessor; @@ -150,8 +150,8 @@ namespace test { } template - typename enable_if< is_TupleListType >, - string >::type + enable_if< is_TupleListType>, + string > showDump (Tuple const& tuple) { typedef typename Tuple::Type TypeSeq; @@ -164,8 +164,8 @@ namespace test { } template - typename enable_if< is_TuplePlain, - string >::type + enable_if< is_TuplePlain, + string > showType () { typedef InstantiateChained DumpPrinter; @@ -174,8 +174,8 @@ namespace test { } template - typename enable_if< is_TupleListType, - string >::type + enable_if< is_TupleListType, + string > showType () { typedef InstantiateChained DumpPrinter; diff --git a/tests/library/meta/typelist-diagnostics.hpp b/tests/library/meta/typelist-diagnostics.hpp index 7f1a92abb..14ad3a1bc 100644 --- a/tests/library/meta/typelist-diagnostics.hpp +++ b/tests/library/meta/typelist-diagnostics.hpp @@ -44,12 +44,10 @@ #include "lib/format-string.hpp" #include "lib/meta/util.hpp" -#include #include using std::string; -using boost::enable_if; namespace lib { @@ -187,8 +185,8 @@ namespace meta { /* ===== printing types and contents ===== */ template - typename enable_if< is_Typelist, - string >::type + enable_if< is_Typelist, + string > showType () { typedef InstantiateChained DumpPrinter;