Skip to content

Commit 34cd87e

Browse files
committed
Apply N4502 per LWG Motion 8 at the 2015-05 Lenexa meeting.
http://wiki.edg.com/twiki/bin/view/Wg21lenexa/StrawPolls
1 parent 54fa5df commit 34cd87e

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

general.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,14 @@ <h1>Feature-testing recommendations (Informative)</h1>
248248
<td>201406</td>
249249
<td><code>&lt;experimental/type_traits></code></td>
250250
</tr>
251+
<tr>
252+
<td>N4502</td>
253+
<td>The C++ Detection Idiom</td>
254+
<td><cxx-ref to="meta.detect"></cxx-ref></td>
255+
<td><code>detect</code></td>
256+
<td>201505</td>
257+
<td><code>&lt;experimental/type_traits></code></td>
258+
</tr>
251259
<tr>
252260
<td>N4388</td>
253261
<td>A Proposal to Add a Const-Propagating Wrapper to the Standard Library</th>

utilities.html

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,38 @@ <h1>Header &lt;experimental/type_traits> synopsis</h1>
246246
template &lt;class T>
247247
using raw_invocation_type_t = typename raw_invocation_type&lt;T>::type;
248248

249+
<cxx-ref insynopsis to="meta.detect"></cxx-ref>
250+
template &lt;class...> using void_t = void;
251+
252+
struct nonesuch {
253+
nonesuch() = delete;
254+
~nonesuch() = delete;
255+
nonesuch(nonesuch const&) = delete;
256+
257+
void operator=(nonesuch const&) = delete;
258+
};
259+
260+
template &lt;template&lt;class...> class Op, class... Args>
261+
using is_detected = <i>see below</i>;
262+
template &lt;template&lt;class...> class Op, class... Args>
263+
constexpr bool is_detected_v = is_detected&lt;Op, Args...>::value;
264+
template &lt;template&lt;class...> class Op, class... Args>
265+
using detected_t = <i>see below</i>;
266+
template &lt;class Default, template&lt;class...> class Op, class... Args>
267+
using detected_or = <i>see below</i>;
268+
template &lt;class Default, template&lt;class...> class Op, class... Args>
269+
using detected_or_t = typename detected_or&lt;Default, Op, Args...>::type;
270+
template &lt;class Expected, template&lt;class...> class Op, class... Args>
271+
using is_detected_exact = is_same&lt;Expected, detected_t&lt;Op, Args...>>;
272+
template &lt;class Expected, template&lt;class...> class Op, class... Args>
273+
constexpr bool is_detected_exact_v
274+
= is_detected_exact&lt;Expected, Op, Args...>::value;
275+
template &lt;class To, template&lt;class...> class Op, class... Args>
276+
using is_detected_convertible = is_convertible&lt;detected_t&lt;Op, Args...>, To>;
277+
template &lt;class To, template&lt;class...> class Op, class... Args>
278+
constexpr bool is_detected_convertible_v
279+
= is_detected_convertible&lt;To, Op, Args...>::value;
280+
249281
} // namespace fundamentals_v2
250282
} // namespace experimental
251283
} // namespace std</code></pre>
@@ -390,6 +422,57 @@ <h1>Other type transformations</h1>
390422
</li>
391423
</ul>
392424
</cxx-section>
425+
426+
<cxx-section id="meta.detect">
427+
<h1>Detection idiom</h1>
428+
429+
<pre><code>template &lt;class Default, class AlwaysVoid,
430+
template&lt;class...> class Op, class... Args>
431+
struct DETECTOR { // <i>exposition only</i>
432+
using value_t = false_type;
433+
using type = Default;
434+
};
435+
436+
template &lt;class Default, template&lt;class...> class Op, class... Args>
437+
struct DETECTOR&lt;Default, void_t&lt;Op&lt;Args...>>, Op, Args...> { // <i>exposition only</i>
438+
using value_t = true_type;
439+
using type = Op&lt;Args...>;
440+
};
441+
442+
template &lt;template&lt;class...> class Op, class... Args>
443+
using is_detected = typename DETECTOR&lt;nonesuch, void, Op, Args...>::value_t;
444+
445+
template &lt;template&lt;class...> class Op, class... Args>
446+
using detected_t = typename DETECTOR&lt;nonesuch, void, Op, Args...>::type;
447+
448+
template &lt;class Default, template&lt;class...> class Op, class... Args>
449+
using detected_or = DETECTOR&lt;Default, void, Op, Args...>;</code></pre>
450+
451+
<cxx-example>
452+
<pre><code>// <i>archetypal helper alias for a copy assignment operation:</i>
453+
template &lt;class T>
454+
using copy_assign_t = decltype(declval&lt;T&>() = declval&lt;T const &>());
455+
456+
// <i>plausible implementation for the is_assignable type trait:</i>
457+
template &lt;class T>
458+
using is_copy_assignable = is_detected&lt;T, copy_assign_t>;
459+
460+
// <i>plausible implementation for an augmented is_assignable type trait</i>
461+
// <i>that also checks the return type:</i>
462+
template &lt;class T>
463+
using is_canonical_copy_assignable = is_detected_exact&lt;T&, T, copy_assign_t>;</code></pre>
464+
</cxx-example>
465+
466+
<cxx-example>
467+
<pre><code>// <i>archetypal helper alias for a particular type member:</i>
468+
template &lt;class T>
469+
using diff_t = typename T::difference_type;
470+
471+
// <i>alias the type member, if it exists, otherwise alias </i>ptrdiff_t<i>:</i>
472+
template &lt;class Ptr>
473+
using difference_type = detected_or_t&lt;ptrdiff_t, diff_t, Ptr>;</code></pre>
474+
</cxx-example>
475+
</cxx-section>
393476
</cxx-section>
394477

395478
<cxx-section id="ratio">

0 commit comments

Comments
 (0)