Topic: A SFINAE-friendly typedef member for predicate-like type_traits
Author: Paul Keir <graham.keir@gmail.com>
Date: Mon, 2 Jul 2018 01:39:23 -0700 (PDT)
Raw View
------=_Part_37912_1741801813.1530520763624
Content-Type: multipart/alternative;
boundary="----=_Part_37913_1911890452.1530520763626"
------=_Part_37913_1911890452.1530520763626
Content-Type: text/plain; charset="UTF-8"
In summary I propose the addition of a SFINAE-friendly typedef member type
sfinae_type, assigned to void, to all of the boolean predicate type traits
in the standard library.
Type traits corresponding to binary predicates give their boolean result in
different ways. Most commonly, the instantiated type will contain a
constant data member named value which is equal either to true or false.
This idiom can be observed in most type traits; such as std::is_void,
std::is_fundamental or std::is_const. For example:
static_assert(true == is_same<char,char>::value);
static_assert(false == is_volatile<char>::value);
For other type traits, the result is a member typedef type. For example,
std::add_pointer or std::decay. Furthermore, the type member result of some
such traits, may or may not exist. Consequently the presence, or absence,
of a typedef member within the instantiated type can correlate with true or
false respectively. std::common_type, std::iterator_traits and
std::result_of execute this approach. For example:
iterator_traits<vector<int>::iterator>::difference_type diff_t;
common_type<int,int*>::type ct_t; // error
result_of<plus<int>(int,char*)>::type ro_t; // error
The latter approach can be described as SFINAE-friendly, in that a
non-existent trait result will not produce an error when involved in an
invalid substitution of template parameters. For example, consider the use
of std::common_type_t in the definition of the overloaded binary subtract
operator for std::duration. Shown below, this function will not be
instantiated when there is insufficient commonality between the types of
its two arguments:
template <class Rep1, class Period1, class Rep2, class Period2>
common_type_t<duration<Rep1, Period1>, duration<Rep2, Period2>>
constexpr operator-( const duration<Rep1, Period1>& lhs
, const duration<Rep2, Period2>& rhs
);
We propose that a SFINAE-friendly member typedef type named sfinae_type
assigned to void be added to all binary predicate type traits. For example,
whereas std::is_same<char,int>::sfinae_type would not be a valid name;
std::is_scalar<int>::sfinae_type would be. Consequently, a function valid
only for arguments of arithmetic type could be written:
template <class T>
typename is_arithmetic<T>::sfinae_type
arith_ok(T t) { cout << "T is an arithmetic type\n"; }
The useful C++17 type trait std::void_t then allows a conjunction of
standard traits:
template<typename T, typename... Ts>
void_t<typename is_same<T, Ts>::sfinae_type...>
func(T, Ts...) { cout << "all types in pack are T\n"; }
Type traits such as std::enable_if and std::void_t facilitate further
composition of predicates in the construction of SFINAE type expressions.
The sfinae_type member would also be added to the C++17 traits
std::conjunction, std::disjunction, and std::negate. Consequently, a
function which is valid for arguments of arithmetic type, but not types
which are an std::nullptr_t or an enumeration type could look as follows:
template <class T>
typename conjunction<
is_scalar<T>,
negation< disjunction< is_null_pointer<T>, is_enum<T> > >
>::sfinae_type
arith_ptr_or_memptr(T) { cout << "arithmetic, ptr, or member ptr\n"; }
Sample code is available at https://wandbox.org/permlink/o0fIFssB6Gl6oRKS.
The code uses the mk_sfinae helper to construct a trait from an existing
trait and its template arguments.
Feedback is most welcome.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/17994533-9542-4403-b447-963cb85d29e6%40isocpp.org.
------=_Part_37913_1911890452.1530520763626
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>In summary I propose the addition of a SFINAE-friendl=
y typedef member type <span style=3D"font-family: courier new, monospace;">=
sfinae_type</span>, assigned to void, to all of the boolean predicate type =
traits in the standard library.</div><div><br></div><div>Type traits corres=
ponding to binary predicates give their boolean result in different ways. M=
ost commonly, the instantiated type will contain a constant data member nam=
ed <span style=3D"font-family: courier new, monospace;">value</span> which =
is equal either to <span style=3D"font-family: courier new, monospace;">tru=
e</span> or <span style=3D"font-family: courier new, monospace;">false</spa=
n>. This idiom can be observed in most type traits; such as <span style=3D"=
font-family: courier new, monospace;">std::is_void</span>, <span style=3D"f=
ont-family: courier new, monospace;">std::is_fundamental</span> or <span st=
yle=3D"font-family: courier new, monospace;">std::is_const</span>. For exam=
ple:<br><br><div style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; overflow-wra=
p: break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div clas=
s=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">static_assert</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">tr=
ue</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =C2=A0<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D=3D</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> is_same</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span =
style=3D"color: #008;" class=3D"styled-by-prettify">char</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">char</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">>::</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify">value</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">static_assert</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">false</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D=3D</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> is_volatile</=
span><span style=3D"color: #080;" class=3D"styled-by-prettify"><char>=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">value</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">);</span></div></code><=
/div><br>For other type traits, the result is a member typedef type. For ex=
ample, <span style=3D"font-family: courier new, monospace;">std::add_pointe=
r</span> or <span style=3D"font-family: courier new, monospace;">std::decay=
</span>. Furthermore, the type member result of some such traits, may or ma=
y not exist. Consequently the presence, or absence, of a typedef member wit=
hin the instantiated type can correlate with true or false respectively. <s=
pan style=3D"font-family: courier new, monospace;">std::common_type</span>,=
<span style=3D"font-family: courier new, monospace;">std::iterator_traits<=
/span> and <span style=3D"font-family: courier new, monospace;">std::result=
_of</span> execute this approach. For example:<br><br><div style=3D"backgro=
und-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-sty=
le: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettypr=
int"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #000;" class=3D"styled-by-prettify">iterator_traits</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">vector</span><span style=3D"=
color: #080;" class=3D"styled-by-prettify"><int></span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">iterator</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">>::</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify">difference_type diff_t</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br>common_type</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">int</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">,</span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">int</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">*>::</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">type =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ct_t</span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by=
-prettify">// error</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br>result_of</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">plus</span><span style=3D"color: #080;" class=3D"styled-by-prettify">=
<int></span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">char</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">*)>::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">type =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ro_t</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"st=
yled-by-prettify">// error</span></div></code></div><br>The latter approach=
can be described as SFINAE-friendly, in that a non-existent trait result w=
ill not produce an error when involved in an invalid substitution of templa=
te parameters. For example, consider the use of <span style=3D"font-family:=
courier new, monospace;">std::common_type_t</span> in the definition of th=
e overloaded binary subtract operator for <span style=3D"font-family: couri=
er new, monospace;">std::duration</span>. Shown below, this function will n=
ot be instantiated when there is insufficient commonality between the types=
of its two arguments:<br><br><div style=3D"background-color: rgb(250, 250,=
250); border-color: rgb(187, 187, 187); border-style: solid; border-width:=
1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"pret=
typrint"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=
=3D"styled-by-prettify">template</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify"><</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">class</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Rep1<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">class</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #60=
6;" class=3D"styled-by-prettify">Period1</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">class</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Re=
p2</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">class</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
606;" class=3D"styled-by-prettify">Period2</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">></span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br>common_type_t</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">duration</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify"><</span><span style=3D"color: #606;" class=3D"s=
tyled-by-prettify">Rep1</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Perio=
d1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>,</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> duration</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><sp=
an style=3D"color: #606;" class=3D"styled-by-prettify">Rep2</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;=
" class=3D"styled-by-prettify">Period2</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">>></span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">constexpr</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">operator</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">-(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">const</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> duration</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><spa=
n style=3D"color: #606;" class=3D"styled-by-prettify">Rep1</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #606;"=
class=3D"styled-by-prettify">Period1</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">>&</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> lhs<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=
=C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
const</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> dura=
tion</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</=
span><span style=3D"color: #606;" class=3D"styled-by-prettify">Rep2</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"colo=
r: #606;" class=3D"styled-by-prettify">Period2</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">>&</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> rhs<br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">);</span></div></code></div><br>We propose that=
a SFINAE-friendly member typedef type named <span style=3D"font-family: co=
urier new, monospace;">sfinae_type</span> assigned to void be added to all =
binary predicate type traits. For example, whereas <span style=3D"font-fami=
ly: courier new, monospace;">std::is_same<char,int>::sfinae_type</spa=
n> would not be a valid name; <span style=3D"font-family: courier new, mono=
space;">std::is_scalar<int>::sfinae_type</span> would be. Consequentl=
y, a function valid only for arguments of arithmetic type could be written:=
<br><br><div style=3D"background-color: rgb(250, 250, 250); border-color: r=
gb(187, 187, 187); border-style: solid; border-width: 1px; overflow-wrap: b=
reak-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D=
"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">=
template</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">class</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">></span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">typename</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> is_arithmetic</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">>::</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">sfinae_type<br>arith_ok</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">T t</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> cout </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify"><<</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #080;" class=3D"styled-by-prettify">"T is an arithmetic =
type\n"</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></=
code></div></div><div><br></div><div>The useful C++17 type trait <span styl=
e=3D"font-family: courier new, monospace;">std::void_t</span> then allows a=
conjunction of standard traits:<br><br><div style=3D"background-color: rgb=
(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bor=
der-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code cla=
ss=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008=
;" class=3D"styled-by-prettify">template</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify"><</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">typename</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> T</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">ty=
pename</span><span style=3D"color: #660;" class=3D"styled-by-prettify">...<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><sp=
an style=3D"color: #606;" class=3D"styled-by-prettify">Ts</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">></span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>void_t</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">typename</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> is_same</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Ts=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>::</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">sfinae_type</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">...></span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>func</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D=
"styled-by-prettify">Ts</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">...)</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> cout </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify"><<</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #080;" class=3D"styled-by-prettify">"all types in pack ar=
e T\n"</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></c=
ode></div><br>Type traits such as <span style=3D"font-family: courier new, =
monospace;">std::enable_if</span> and <span style=3D"font-family: courier n=
ew, monospace;">std::void_t</span> facilitate further composition of predic=
ates in the construction of SFINAE type expressions. The <span style=3D"fon=
t-family: courier new, monospace;">sfinae_type</span> member would also be =
added to the C++17 traits <span style=3D"font-family: courier new, monospac=
e;">std::conjunction</span>, <span style=3D"font-family: courier new, monos=
pace;">std::disjunction</span>, and <span style=3D"font-family: courier new=
, monospace;">std::negate</span>. Consequently, a function which is valid f=
or arguments of arithmetic type, but not types which are an <span style=3D"=
font-family: courier new, monospace;">std::nullptr_t</span> or an enumerati=
on type could look as follows:</div><div><br><div style=3D"background-color=
: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid=
; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><cod=
e class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color:=
#008;" class=3D"styled-by-prettify">template</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify"><</span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">class</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> T</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">></span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">typen=
ame</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> conjun=
ction</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0is_scalar</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">>,</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0negation</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> disjunction</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> is_null_pointer</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">>,</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> is_enum</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">></span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">></span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">>::</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">sfinae_type<br>arith_ptr_or_memptr</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">T</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> cout </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify"><<</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #080;" class=3D"styled-by-prettify">"arithmetic, ptr, or me=
mber ptr\n"</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span></di=
v></code></div><br>Sample code is available at <a href=3D"https://wandbox.o=
rg/permlink/o0fIFssB6Gl6oRKS">https://wandbox.org/permlink/o0fIFssB6Gl6oRKS=
</a>. The code uses the <span style=3D"font-family: courier new, monospace;=
">mk_sfinae</span> helper to construct a trait from an existing trait and i=
ts template arguments.<br></div><div><br></div><div>Feedback is most welcom=
e.<br></div></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/17994533-9542-4403-b447-963cb85d29e6%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/17994533-9542-4403-b447-963cb85d29e6=
%40isocpp.org</a>.<br />
------=_Part_37913_1911890452.1530520763626--
------=_Part_37912_1741801813.1530520763624--
.