From ea8a99c2abc8d8ae4bdbd5b1ea75ed2219c166dd Mon Sep 17 00:00:00 2001 From: badair Date: Fri, 15 Apr 2016 00:39:44 -0500 Subject: [PATCH] Updating FAQ --- doc/callable_traits.qbk | 90 +++++++++++++- doc/html/callable_traits/faq.html | 138 ++++++++++++++++++++- doc/html/index.html | 27 +++- include/callable_traits/detail/any_arg.hpp | 3 +- 4 files changed, 247 insertions(+), 11 deletions(-) diff --git a/doc/callable_traits.qbk b/doc/callable_traits.qbk index 23e3b15..8c744d6 100644 --- a/doc/callable_traits.qbk +++ b/doc/callable_traits.qbk @@ -160,8 +160,8 @@ This documentation will be most beneficial to readers who posess a basic underst * function types * [@http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_functions function pointers] * [@http://stackoverflow.com/questions/480248/function-references function references] -* [@http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_member_functions pointers to member functions] -* [@http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_data_members pointers to data members] +* [@http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_member_functions pointers to member functions] (a.k.a. PMFs) +* [@http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_data_members pointers to data members] (a.k.a. PMDs) * [@http://en.cppreference.com/w/cpp/language/operators#Function_call_operator the function call operator, [^operator()]] * [@https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers universal references] and [@http://stackoverflow.com/questions/13725747/concise-explanation-of-reference-collapsing-rules-requested-1-a-a-2 reference collapsing rules] * [@http://en.cppreference.com/w/cpp/language/member_functions#const-.2C_volatile-.2C_and_ref-qualified_member_functions cv-qualified and ref-qualified member functions] @@ -175,6 +175,11 @@ This documentation will be most beneficial to readers who posess a basic underst [section:motivation Motivation] +[:[*['["Don't try to write helper code to detect PMFs/PMDs and dispatch on them -- it is an [_absolute nightmare]. PMF types are the worst types by far in the core language.]]] + +-- Stephan T. Lavavej, CppCon 2015, [@https://www.youtube.com/watch?v=zt7ThwVfap0&t=11m40s "functional: What's New, And Proper Usage"] +] + Consider for a moment the class template below, which defines all [role red[*48]] template specializations necessary to account for all valid function types and member function pointer types in C++11 and C++14: [import ./hideous_template.snippet.cpp] @@ -296,6 +301,66 @@ While most of the features in [libname] are tested and working in MSVC, the foll [section:faq FAQ] + +[section:reasons Why should I use [libname]?] + +If you are not writing generic code, you simply shouldn't. + +If you ['are] writing generic code, take a moment to skim your header files, looking for code like this: + + template + class foo { + // ^^^^^^^^^^^^^^^^^^^^^ + }; + +or like this... + + template + class foo { + // ^^^^^^^^^^^^^^^ + }; + +or maybe something like this... + + template + class foo { + // ^^^^^^^^^^^^^^^^^^ + }; + +perhaps... + + template + class foo { + // ^^^^^^^^^^^^^^^^^^ + }; + +Does this rings a bell? + + template + class foo { + // ^^^^^^^^^^^^^^^^^^^^^ + }; + +Do you hate your job? + + template + class foo { + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + }; + +Do you seek revenge against your coworkers? + + #define EXPAND_LIKE_THE_DICKENS(QUALIFIERS) \ + template \ + class foo { \ + /* ... */ \ + }; + +Implementers of the `` header have been trudging through code like this for years. The solution can absolutely refactor it into something much smaller, much more readable, and much more maintainable. +There are real reasons to write code like this, but they are few and far between. [libname]'s mission is to rid the world of code like this, [*forever]. [libname] + +[endsect] + [section:reasons What makes [libname] unique?] [*1.] [libname] offers template aliases such as [link_remove_member_const] for manipulating function qualifiers, designed to parallel the `` aliases such as `std::remove_const_t`. @@ -322,10 +387,29 @@ While most of the features in [libname] are tested and working in MSVC, the foll [section Why does [namespace_scoped][^args] alias a [^std::tuple]?] -Boost contains a handful of excellent type containers. However, I wanted [libname] to only use the standard headers, so `` was my only option under that limitation. +Boost contains a handful of excellent type containers. However, [libname] is designed to only use the standard headers, so `` was the only option under this limitation. [endsect] +[section Why are the [libname] alias templates not suffixed with `_t`, as in `std::add_lvalue_reference_t`?] + +The `_t` alias templates in `` should be appreciated, but not imitated. These alias templates were a belated addition to the standard library. They use a cleaner syntax, so that users can forgo the `typename /*...*/::type` dance. However, it is both ironic and unfortunate that a pair of unnecessary characters (`_t`) are used for the sole purpose of removing some ['other] decidedly unnecessary characters (`typename` and `::type`). It's time to stop the bleeding, cut our losses, and start giving things sensible names. + +[endsect] + +[section Why use constexpr function templates? Why not use something like `std::is_same` or even `std::is_same_v`?] + +Function templates, especially when augmented by overloading them, are the only constructs in C++ that can unequivocally accept ['either] a type ['or] a value argument. Even if variable template support were commonplace among production compilers, function templates would still have the upper hand in this regard. The same argument applies to alias templates and class templates. Since [libname] supports all value categories and qualifiers, using these function templates really couldn't be any easier. + +[endsect] + +[section Why use reference collapsing rules when adding member function ref-qualifiers?] + +Although arbitrary, the reference collapsing rules are well-defined and already known to template metaprogrammers. Anything else would be a burden to memorize. + +[endsect] + + [endsect] diff --git a/doc/html/callable_traits/faq.html b/doc/html/callable_traits/faq.html index 7610653..3b8ec0d 100644 --- a/doc/html/callable_traits/faq.html +++ b/doc/html/callable_traits/faq.html @@ -27,14 +27,96 @@ FAQ
+

+ If you are not writing generic code, you simply shouldn't. +

+

+ If you are writing generic code, take a moment to skim + your header files, looking for code like this: +

+
template<class Return, class First, class Second>
+class foo<Return(First, Second)> {
+    //     ^^^^^^^^^^^^^^^^^^^^^
+};
+
+

+ or like this... +

+
template<class Return, class ...Args>
+class foo<Return(Args...)> {
+    //     ^^^^^^^^^^^^^^^
+};
+
+

+ or maybe something like this... +

+
template<class Return, class ...Args>
+class foo<Return(*)(Args...)> {
+    //     ^^^^^^^^^^^^^^^^^^
+};
+
+

+ perhaps... +

+
template<class Return, class ...Args>
+class foo<Return(&)(Args...)> {
+    //    ^^^^^^^^^^^^^^^^^^
+};
+
+

+ Does this rings a bell? +

+
template<class Return, class T, class ...Args>
+class foo<Return(T::*)(Args...)> {
+    //    ^^^^^^^^^^^^^^^^^^^^^
+};
+
+

+ Do you hate your job? +

+
template<class Return, class T, class ...Args>
+class foo<Return( __cdecl T::* const volatile &)(Args..., ...) const volatile &&> {
+    //    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+};
+
+

+ Do you seek revenge against your coworkers? +

+
#define EXPAND_LIKE_THE_DICKENS(QUALIFIERS)    \
+template<class Return, class T, class ...Args> \
+class foo<Return(T::*)(Args...) QUALIFIERS> {  \
+    /* ... */                                  \
+};
+
+

+ There are real reasons to write code like this, but they are few and far + between. CallableTraits's mission is to rid the world + of this code forever. If you have code like this, you can absolutely refactor + it into something much smaller, much more readable, and much more maintainable. + CallableTraits +

+
+
+

@@ -112,8 +194,56 @@ does callable_traits::args alias a std::tuple?

- Boost contains a handful of excellent type containers. However, I wanted - CallableTraits to only use the standard headers, so <tuple> was my only option under that limitation. + Boost contains a handful of excellent type containers. However, CallableTraits + is designed to only use the standard headers, so <tuple> + was the only option under this limitation. +

+ +
+ +

+ The _t alias templates in + <type_traits> should be appreciated, but not imitated. + These alias templates were a belated addition to the standard library. They + use a cleaner syntax, so that users can forgo the typename + /*...*/::type dance. However, it is both ironic + and unfortunate that a pair of unnecessary characters (_t) + are used for the sole purpose of removing some other + decidedly unnecessary characters (typename + and ::type). + It's time to stop the bleeding, cut our losses, and start giving things sensible + names. +

+
+
+ +

+ Function templates, especially when augmented by overloading them, are the + only constructs in C++ that can unequivocally accept either + a type or a value argument. Even if variable template + support were commonplace among production compilers, function templates would + still have the upper hand in this regard. The same argument applies to alias + templates and class templates. Since CallableTraits supports + all value categories and qualifiers, using these function templates really + couldn't be any easier. +

+
+
+ +

+ Although arbitrary, the reference collapsing rules are well-defined and already + known to template metaprogrammers. Anything else would be a burden to memorize.

diff --git a/doc/html/index.html b/doc/html/index.html index 7f0d1a3..f74936c 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -51,10 +51,19 @@
MSVC Issues
FAQ
-
What makes CallableTraits +
Why should I use CallableTraits?
+
What makes CallableTraits unique?
Why does callable_traits::args alias a std::tuple?
+
Why + are the CallableTraits alias templates not suffixed with + _t, as in std::add_lvalue_reference_t?
+
Why + use constexpr function templates? Why not use something like std::is_same + or even std::is_same_v?
+
Why + use reference collapsing rules when adding member function ref-qualifiers?
Contact
Concepts
@@ -193,11 +202,11 @@
  • pointers - to member functions + to member functions (a.k.a. PMFs)
  • pointers - to data members + to data members (a.k.a. PMDs)
  • the @@ -238,6 +247,18 @@ +
    +

    + Don't try to write helper code to + detect PMFs/PMDs and dispatch on them -- it is an absolute + nightmare. PMF types are the worst types by far in the core + language. +

    +

    + -- Stephan T. Lavavej, CppCon 2015, "functional: + What's New, And Proper Usage" +

    +

    Consider for a moment the class template below, which defines all 48 template specializations necessary to account for all valid function types and member function pointer diff --git a/include/callable_traits/detail/any_arg.hpp b/include/callable_traits/detail/any_arg.hpp index 80aa08a..ab7e47a 100644 --- a/include/callable_traits/detail/any_arg.hpp +++ b/include/callable_traits/detail/any_arg.hpp @@ -11,6 +11,7 @@ Distributed under the Boost Software License, Version 1.0. #define CALLABLE_TRAITS_DETAIL_ANY_ARG_HPP #include +#include #include #include @@ -47,7 +48,7 @@ namespace callable_traits { #if !defined(CALLABLE_TRAITS_MSVC) //MSVC doesn't like this because it can deduce 'void' template - any_arg_evaluated(T&&...); + any_arg_evaluated(T&&...){} #endif //!defined(CALLABLE_TRAITS_MSVC) inline constexpr auto operator+() const { return type{}; }