Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The presence of a non-templated <em>T::operator()</em> for a given type <em>T</em> can be detected by:</p> <pre><code>template&lt;typename C&gt; // detect regular operator() static char test(decltype(&amp;C::operator())); template&lt;typename C&gt; // worst match static char (&amp;test(...))[2]; static const bool value = (sizeof( test&lt;T&gt;(0) ) </code></pre> <p>The presence of a templated operator can be detected by: </p> <pre><code>template&lt;typename F, typename A&gt; // detect 1-arg operator() static char test(int, decltype( (*(F*)0)( (*(A*)0) ) ) = 0); template&lt;typename F, typename A, typename B&gt; // detect 2-arg operator() static char test(int, decltype( (*(F*)0)( (*(A*)0), (*(B*)0) ) ) = 0); // ... detect N-arg operator() template&lt;typename F, typename ...Args&gt; // worst match static char (&amp;test(...))[2]; static const bool value = (sizeof( test&lt;T, int&gt;(0) ) == 1) || (sizeof( test&lt;T, int, int&gt;(0) ) == 1); // etc... </code></pre> <p>However, these two do not play nicely together, as <em>decltype(&amp;C::operator())</em> will produce an error if C has a templated function call operator. The solution is to run the sequence of checks against a templated operator first, and check for a regular operator() <em>if and only if</em> a templated one can not be found. This is done by specializing the non-templated check to a no-op if a templated one was found.</p> <pre><code>template&lt;bool, typename T&gt; struct has_regular_call_operator { template&lt;typename C&gt; // detect regular operator() static char test(decltype(&amp;C::operator())); template&lt;typename C&gt; // worst match static char (&amp;test(...))[2]; static const bool value = (sizeof( test&lt;T&gt;(0) ) == 1); }; template&lt;typename T&gt; struct has_regular_call_operator&lt;true,T&gt; { static const bool value = true; }; template&lt;typename T&gt; struct has_call_operator { template&lt;typename F, typename A&gt; // detect 1-arg operator() static char test(int, decltype( (*(F*)0)( (*(A*)0) ) ) = 0); template&lt;typename F, typename A, typename B&gt; // detect 2-arg operator() static char test(int, decltype( (*(F*)0)( (*(A*)0), (*(B*)0) ) ) = 0); template&lt;typename F, typename A, typename B, typename C&gt; // detect 3-arg operator() static char test(int, decltype( (*(F*)0)( (*(A*)0), (*(B*)0), (*(C*)0) ) ) = 0); template&lt;typename F, typename ...Args&gt; // worst match static char (&amp;test(...))[2]; static const bool OneArg = (sizeof( test&lt;T, int&gt;(0) ) == 1); static const bool TwoArg = (sizeof( test&lt;T, int, int&gt;(0) ) == 1); static const bool ThreeArg = (sizeof( test&lt;T, int, int, int&gt;(0) ) == 1); static const bool HasTemplatedOperator = OneArg || TwoArg || ThreeArg; static const bool value = has_regular_call_operator&lt;HasTemplatedOperator, T&gt;::value; }; </code></pre> <p>If the arity is always one, as discussed above, then the check should be simpler. I do not see the need for any additional type traits or library facilities for this to work.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload