Updating FAQ

This commit is contained in:
badair
2016-04-15 00:39:44 -05:00
parent 6aaab21aa8
commit ea8a99c2ab
4 changed files with 247 additions and 11 deletions

View File

@@ -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 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> { \
/* ... */ \
};
Implementers of the `<functional>` 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 `<type_traits>` 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 `<tuple>` 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 `<tuple>` 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 `<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.
[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]

View File

@@ -27,14 +27,96 @@
<a name="callable_traits.faq"></a><a class="link" href="faq.html" title="FAQ">FAQ</a>
</h2></div></div></div>
<div class="toc"><dl class="toc">
<dt><span class="section"><a href="faq.html#callable_traits.faq.reasons">What makes <code class="literal">CallableTraits</code>
<dt><span class="section"><a href="faq.html#callable_traits.faq.reasons">Why should I use <code class="literal">CallableTraits</code>?</a></span></dt>
<dt><span class="section"><a href="faq.html#callable_traits.faq.reasons0">What makes <code class="literal">CallableTraits</code>
unique?</a></span></dt>
<dt><span class="section"><a href="faq.html#callable_traits.faq.why_does_namespace_scoped_args_a">Why
does <code class="literal">callable_traits::</code><code class="literal">args</code> alias a <code class="literal">std::tuple</code>?</a></span></dt>
<dt><span class="section"><a href="faq.html#callable_traits.faq.why_are_the_libname_alias_templa">Why
are the <code class="literal">CallableTraits</code> alias templates not suffixed with
<code class="computeroutput"><span class="identifier">_t</span></code>, as in <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">add_lvalue_reference_t</span></code>?</a></span></dt>
<dt><span class="section"><a href="faq.html#callable_traits.faq.why_use_constexpr_function_templ">Why
use constexpr function templates? Why not use something like <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span></code>
or even <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same_v</span></code>?</a></span></dt>
<dt><span class="section"><a href="faq.html#callable_traits.faq.why_use_reference_collapsing_rul">Why
use reference collapsing rules when adding member function ref-qualifiers?</a></span></dt>
</dl></div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="callable_traits.faq.reasons"></a><a class="link" href="faq.html#callable_traits.faq.reasons" title="What makes CallableTraits unique?">What makes <code class="literal">CallableTraits</code>
<a name="callable_traits.faq.reasons"></a><a class="link" href="faq.html#callable_traits.faq.reasons" title="Why should I use CallableTraits?">Why should I use <code class="literal">CallableTraits</code>?</a>
</h3></div></div></div>
<p>
If you are not writing generic code, you simply shouldn't.
</p>
<p>
If you <span class="emphasis"><em>are</em></span> writing generic code, take a moment to skim
your header files, looking for code like this:
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">First</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Second</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">First</span><span class="special">,</span> <span class="identifier">Second</span><span class="special">)&gt;</span> <span class="special">{</span>
<span class="comment">// ^^^^^^^^^^^^^^^^^^^^^</span>
<span class="special">};</span>
</pre>
<p>
or like this...
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="special">...</span><span class="identifier">Args</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">Args</span><span class="special">...)&gt;</span> <span class="special">{</span>
<span class="comment">// ^^^^^^^^^^^^^^^</span>
<span class="special">};</span>
</pre>
<p>
or maybe something like this...
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="special">...</span><span class="identifier">Args</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(*)(</span><span class="identifier">Args</span><span class="special">...)&gt;</span> <span class="special">{</span>
<span class="comment">// ^^^^^^^^^^^^^^^^^^</span>
<span class="special">};</span>
</pre>
<p>
perhaps...
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="special">...</span><span class="identifier">Args</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(&amp;)(</span><span class="identifier">Args</span><span class="special">...)&gt;</span> <span class="special">{</span>
<span class="comment">// ^^^^^^^^^^^^^^^^^^</span>
<span class="special">};</span>
</pre>
<p>
Does this rings a bell?
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="special">...</span><span class="identifier">Args</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...)&gt;</span> <span class="special">{</span>
<span class="comment">// ^^^^^^^^^^^^^^^^^^^^^</span>
<span class="special">};</span>
</pre>
<p>
Do you hate your job?
</p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="special">...</span><span class="identifier">Args</span><span class="special">&gt;</span>
<span class="keyword">class</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span> <span class="identifier">__cdecl</span> <span class="identifier">T</span><span class="special">::*</span> <span class="keyword">const</span> <span class="keyword">volatile</span> <span class="special">&amp;)(</span><span class="identifier">Args</span><span class="special">...,</span> <span class="special">...)</span> <span class="keyword">const</span> <span class="keyword">volatile</span> <span class="special">&amp;&amp;&gt;</span> <span class="special">{</span>
<span class="comment">// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span>
<span class="special">};</span>
</pre>
<p>
Do you seek revenge against your coworkers?
</p>
<pre class="programlisting"><span class="preprocessor">#define</span> <span class="identifier">EXPAND_LIKE_THE_DICKENS</span><span class="special">(</span><span class="identifier">QUALIFIERS</span><span class="special">)</span> <span class="special">\</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Return</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">T</span><span class="special">,</span> <span class="keyword">class</span> <span class="special">...</span><span class="identifier">Args</span><span class="special">&gt;</span> <span class="special">\</span>
<span class="keyword">class</span> <span class="identifier">foo</span><span class="special">&lt;</span><span class="identifier">Return</span><span class="special">(</span><span class="identifier">T</span><span class="special">::*)(</span><span class="identifier">Args</span><span class="special">...)</span> <span class="identifier">QUALIFIERS</span><span class="special">&gt;</span> <span class="special">{</span> <span class="special">\</span>
<span class="comment">/* ... */</span> <span class="special">\</span>
<span class="special">};</span>
</pre>
<p>
There are real reasons to write code like this, but they are few and far
between. <code class="literal">CallableTraits</code>'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.
<code class="literal">CallableTraits</code>
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="callable_traits.faq.reasons0"></a><a class="link" href="faq.html#callable_traits.faq.reasons0" title="What makes CallableTraits unique?">What makes <code class="literal">CallableTraits</code>
unique?</a>
</h3></div></div></div>
<p>
@@ -112,8 +194,56 @@
does <code class="literal">callable_traits::</code><code class="literal">args</code> alias a <code class="literal">std::tuple</code>?</a>
</h3></div></div></div>
<p>
Boost contains a handful of excellent type containers. However, I wanted
<code class="literal">CallableTraits</code> to only use the standard headers, so <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">tuple</span><span class="special">&gt;</span></code> was my only option under that limitation.
Boost contains a handful of excellent type containers. However, <code class="literal">CallableTraits</code>
is designed to only use the standard headers, so <code class="computeroutput"><span class="special">&lt;</span><span class="identifier">tuple</span><span class="special">&gt;</span></code>
was the only option under this limitation.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="callable_traits.faq.why_are_the_libname_alias_templa"></a><a class="link" href="faq.html#callable_traits.faq.why_are_the_libname_alias_templa" title="Why are the CallableTraits alias templates not suffixed with _t, as in std::add_lvalue_reference_t?">Why
are the <code class="literal">CallableTraits</code> alias templates not suffixed with
<code class="computeroutput"><span class="identifier">_t</span></code>, as in <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">add_lvalue_reference_t</span></code>?</a>
</h3></div></div></div>
<p>
The <code class="computeroutput"><span class="identifier">_t</span></code> alias templates in
<code class="computeroutput"><span class="special">&lt;</span><span class="identifier">type_traits</span><span class="special">&gt;</span></code> 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 <code class="computeroutput"><span class="keyword">typename</span>
<span class="comment">/*...*/</span><span class="special">::</span><span class="identifier">type</span></code> dance. However, it is both ironic
and unfortunate that a pair of unnecessary characters (<code class="computeroutput"><span class="identifier">_t</span></code>)
are used for the sole purpose of removing some <span class="emphasis"><em>other</em></span>
decidedly unnecessary characters (<code class="computeroutput"><span class="keyword">typename</span></code>
and <code class="computeroutput"><span class="special">::</span><span class="identifier">type</span></code>).
It's time to stop the bleeding, cut our losses, and start giving things sensible
names.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="callable_traits.faq.why_use_constexpr_function_templ"></a><a class="link" href="faq.html#callable_traits.faq.why_use_constexpr_function_templ" title="Why use constexpr function templates? Why not use something like std::is_same or even std::is_same_v?">Why
use constexpr function templates? Why not use something like <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span></code>
or even <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same_v</span></code>?</a>
</h3></div></div></div>
<p>
Function templates, especially when augmented by overloading them, are the
only constructs in C++ that can unequivocally accept <span class="emphasis"><em>either</em></span>
a type <span class="emphasis"><em>or</em></span> 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 <code class="literal">CallableTraits</code> supports
all value categories and qualifiers, using these function templates really
couldn't be any easier.
</p>
</div>
<div class="section">
<div class="titlepage"><div><div><h3 class="title">
<a name="callable_traits.faq.why_use_reference_collapsing_rul"></a><a class="link" href="faq.html#callable_traits.faq.why_use_reference_collapsing_rul" title="Why use reference collapsing rules when adding member function ref-qualifiers?">Why
use reference collapsing rules when adding member function ref-qualifiers?</a>
</h3></div></div></div>
<p>
Although arbitrary, the reference collapsing rules are well-defined and already
known to template metaprogrammers. Anything else would be a burden to memorize.
</p>
</div>
</div>

View File

@@ -51,10 +51,19 @@
<dd><dl><dt><span class="section"><a href="callable_traits/compatibility.html#callable_traits.compatibility.msvc_issues">MSVC Issues</a></span></dt></dl></dd>
<dt><span class="section"><a href="callable_traits/faq.html">FAQ</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="callable_traits/faq.html#callable_traits.faq.reasons">What makes <code class="literal">CallableTraits</code>
<dt><span class="section"><a href="callable_traits/faq.html#callable_traits.faq.reasons">Why should I use <code class="literal">CallableTraits</code>?</a></span></dt>
<dt><span class="section"><a href="callable_traits/faq.html#callable_traits.faq.reasons0">What makes <code class="literal">CallableTraits</code>
unique?</a></span></dt>
<dt><span class="section"><a href="callable_traits/faq.html#callable_traits.faq.why_does_namespace_scoped_args_a">Why
does <code class="literal">callable_traits::</code><code class="literal">args</code> alias a <code class="literal">std::tuple</code>?</a></span></dt>
<dt><span class="section"><a href="callable_traits/faq.html#callable_traits.faq.why_are_the_libname_alias_templa">Why
are the <code class="literal">CallableTraits</code> alias templates not suffixed with
<code class="computeroutput"><span class="identifier">_t</span></code>, as in <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">add_lvalue_reference_t</span></code>?</a></span></dt>
<dt><span class="section"><a href="callable_traits/faq.html#callable_traits.faq.why_use_constexpr_function_templ">Why
use constexpr function templates? Why not use something like <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same</span></code>
or even <code class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">is_same_v</span></code>?</a></span></dt>
<dt><span class="section"><a href="callable_traits/faq.html#callable_traits.faq.why_use_reference_collapsing_rul">Why
use reference collapsing rules when adding member function ref-qualifiers?</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="callable_traits/contact.html">Contact</a></span></dt>
<dt><span class="section"><a href="callable_traits/concepts.html">Concepts</a></span></dt>
@@ -193,11 +202,11 @@
</li>
<li class="listitem">
<a href="http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_member_functions" target="_top">pointers
to member functions</a>
to member functions</a> (a.k.a. PMFs)
</li>
<li class="listitem">
<a href="http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_data_members" target="_top">pointers
to data members</a>
to data members</a> (a.k.a. PMDs)
</li>
<li class="listitem">
<a href="http://en.cppreference.com/w/cpp/language/operators#Function_call_operator" target="_top">the
@@ -238,6 +247,18 @@
<div class="titlepage"><div><div><h3 class="title">
<a name="callable_traits.introduction.motivation"></a><a class="link" href="index.html#callable_traits.introduction.motivation" title="Motivation">Motivation</a>
</h3></div></div></div>
<div class="blockquote"><blockquote class="blockquote">
<p>
<span class="bold"><strong><span class="emphasis"><em><span class="quote">&#8220;<span class="quote">Don't try to write helper code to
detect PMFs/PMDs and dispatch on them -- it is an <span class="underline">absolute
nightmare</span>. PMF types are the worst types by far in the core
language.</span>&#8221;</span></em></span></strong></span>
</p>
<p>
-- Stephan T. Lavavej, CppCon 2015, <a href="https://www.youtube.com/watch?v=zt7ThwVfap0&amp;t=11m40s" target="_top">"functional:
What's New, And Proper Usage"</a>
</p>
</blockquote></div>
<p>
Consider for a moment the class template below, which defines all <span class="red"><span class="bold"><strong>48</strong></span></span> template specializations
necessary to account for all valid function types and member function pointer

View File

@@ -11,6 +11,7 @@ Distributed under the Boost Software License, Version 1.0.
#define CALLABLE_TRAITS_DETAIL_ANY_ARG_HPP
#include <utility>
#include <type_traits>
#include <callable_traits/detail/make_constexpr.hpp>
#include <callable_traits/config.hpp>
@@ -47,7 +48,7 @@ namespace callable_traits {
#if !defined(CALLABLE_TRAITS_MSVC)
//MSVC doesn't like this because it can deduce 'void'
template<typename... T>
any_arg_evaluated(T&&...);
any_arg_evaluated(T&&...){}
#endif //!defined(CALLABLE_TRAITS_MSVC)
inline constexpr auto operator+() const { return type{}; }