Topic: User-defined ordering of candidate functions
Author: Nikolay Ivchenkov <tsoae@mail.ru>
Date: Sat, 12 Jan 2013 01:28:22 -0800 (PST)
Raw View
------=_Part_1585_609438.1357982902940
Content-Type: text/plain; charset=ISO-8859-1
Sometimes a function from an overload set is supposed to be called only if
a certain subset of other candidates does not contain viable functions. For
example,
// (1)
template <class T, std::size_t Size>
T *begin(T (&arr)[Size])
{ return arr; }
// (2)
template <class T>
auto begin(T &range) -> decltype(range.begin())
{ return range.begin(); }
namespace impl
{
void begin();
template <class T>
auto begin_impl(T &range) -> decltype(begin(range))
{ return begin(range); }
}
// (3)
template <class T>
auto begin(T &range) -> decltype(impl::begin_impl(range))
{ return impl::begin_impl(range); }
(begin)(expression) is intended to be nearly equivalent to begin-expr in
the range-based for statement
for (for-range-declaration : expression) statement
Unfortunately, this overload set doesn't work as intended, because (2) and
(3) may produce equally viable specializations (so we'll get an ambiguous
call). We have to disable the ADL-based function when (2) would be viable.
This is possible with std::enable_if. Let's assume that we have a core
language facility like this:
is_well_formed_expression(expr) == true iff expr is a well-formed
expression;
is_well_formed_expression(expr) == false iff expr is an ill-formed
expression.
Then we could define (3) as follows:
template <bool C, class T = void>
using enable_if = typename std::enable_if<C, T>::type;
template <class T>
auto begin(T &range) -> enable_if
<
!is_well_formed_expression(range.begin()),
decltype(impl::begin_impl(range))
>
{ return impl::begin_impl(range); }
Although this code doesn't look too complicated, someone could say that we
have a redundancy here: we need to duplicate a condition already expressed
elsewhere. Let's modify the second template:
template <class T>
auto begin(T &range) -> enable_if
<
std::is_same<decltype(range.begin()), decltype(range.end
())>{}
decltype(range.begin())
>
{ return range.begin(); }
Now we have to change the third template accordingly:
template <class T>
auto begin(T &range) -> enable_if
<
!is_well_formed_expression(enable_if<std::is_same<decltype(
range.begin()), decltype(range.end())>{}>()),
decltype(impl::begin_impl(range))
>
{ return impl::begin_impl(range); }
This doesn't look pretty, right? Alternatively, we could use
is_well_formed_expression with static if and auto-deduced return types:
template <class T, std::size_t Size>
T *begin(T (&arr)[Size])
{ return arr; }
namespace impl
{
void begin();
template <class T>
auto begin_impl(T &range)
{ return begin(range); }
}
template <class T>
auto begin(T &range)
{
static if (is_well_formed_expression(enable_if<std::is_same<decltype
(range.begin()), decltype(range.end())>{}>())
{
return range.begin();
}
else
{
return impl::begin_impl(range);
}
}
This looks much better, however, I still would like to consider another
approach.
Let's imagine that every function and function template have an associated
value that represents the order in which the function or function template
would be considered during overload resolution and we can explicitly
specify the order using the following syntax:
function-specifier:
using [ constant-expression ]
....
where the value of the constant-expression represents the order. If for a
given function declaration or function template declaration the order is
not specified explicitly, it is implicitly assumed to be zero. Two
declarations of the same function or function template shall (implicitly or
explicitly) assign the same order to the function. Currently I have no
strong opinion about whether negative order values should be allowed.
Everytime when a set of candidate functions is constructed for some
context, the selection of the best function is performed as follows:
1. First, all candidate functions form a set of remaining candidate
functions; then
2. a subset of the remaining candidate functions with the minimal order is
selected to form a set of currently considered candidate functions; then
3. a subset of the currently considered candidate functions (those that
have the proper number of arguments and meet certain other conditions) is
selected to form a set of viable functions; then
4. if the set of viable functions is empty, then currently considered
candidate functions (determined in step 2) are excluded from the set of
remaining candidate functions and if the resulting set of remaining
candidate functions is non-empty, steps 2 - 4 are performed again in order
to re-evaluate the set of viable functions;
5. finally, the best viable function is selected from the final set of
viable functions according to 13.3.3. If a best viable function exists and
is unique, overload resolution succeeds and produces it as the result;
otherwise overload resolution fails.
Example:
template <bool C, class T = void>
using enable_if = typename std::enable_if<C, T>::type;
// (1) order = 0
template <class T>
auto f(T) -> enable_if<std::is_signed<T>{}>;
// (2) order = 0
template <class T>
using[0] auto f(T) -> enable_if<std::is_floating_point<T>{}>;
// (3) order = 1
template <class T>
using[1] auto f(T) -> enable_if<std::is_arithmetic<T>{}>;
// (4) order = 1
template <class T>
using[1] auto f(T) -> enable_if<std::is_enum<T>{}>;
// (5) order = 2
template <class T>
using[2] auto f(T) -> enable_if<std::is_scalar<T>{}>;
int main()
{
enum { e };
f(0); // calls (1) [ {(1), (2)} => (1) ]
f(0.); // calls (2) [ {(1), (2)} => (2) ]
f(0u); // calls (3) [ {(1), (2)} => none -> {(3), (4)} => (3) ]
f(e); // calls (4) [ {(1), (2)} => none -> {(3), (4)} => (4) ]
f(nullptr); // calls (5) [ {(1), (2)} => none -> {(3), (4)} => none
-> {(5)} => (5) ]
}
The definition of the ADL-based 'begin' in the initial example could be
changed to
template <class T>
using[1] auto begin(T &range) -> decltype(impl::begin_impl(range))
{ return impl::begin_impl(range); }
so it would not be considered unless the other two overloads are non-viable.
Other possible applications:
1)
class any
{
public:
any();
any(any const &);
any(any &&);
template <class T>
using[1] any(T &&);
};
int main()
{
any a1; // a1 is non-const
any a2 = a1; // calls the copy ctor
any a3 = 0u; // calls the template ctor
}
2)
template <class T, class Allocator = allocator<T> >
class vector
{
....
vector(size_type n, T const &value, Allocator const & = Allocator
());
template <class InputIterator>
using[1] vector(InputIterator first, InputIterator last,
Allocator const & = Allocator());
....
};
int main()
{
vector<double> v(2, 1); // calls the non-template ctor
}
3)
using[1] void f(char const *) {}
void f(short) {}
int main()
{
f(0); // calls f(short)
f(nullptr); // calls f(char const *)
}
Was a similar feature ever suggested? Would it be significantly useful?
--
------=_Part_1585_609438.1357982902940
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Sometimes a function from an overload set is supposed to be called only if =
a certain subset of other candidates does not contain viable functions. For=
example,<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(=
250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bord=
er-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div cla=
ss=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #800;" class=3D"styled-by-p=
rettify">// (1)</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br> </span><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">clas=
s</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 sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">size_t </span><span style=3D"color: #606=
;" class=3D"styled-by-prettify">Size</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">></span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br> T </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">*</span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">begin</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-p=
rettify">arr</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">)[</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Size</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">])</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br> &n=
bsp; </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">re=
turn</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> arr</=
span><span 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: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br> </span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">// (2)</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">template</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #0=
08;" 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"color: #000;" class=3D"style=
d-by-prettify"><br> </span><span style=3D"color:=
#008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">begin</span><span style=3D"color: #660;" class=3D"s=
tyled-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">ran=
ge</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: #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-by-prettify">decltype</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">range</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">.</span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">begin</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">())</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> range</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">.</span><span style=3D"color: #008;" class=3D"styled-by-prettify">b=
egin</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</s=
pan><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"><br><br> </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">namespace</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> impl<br> &nbs=
p; </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>  =
; </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">void</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">begin</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br> &nb=
sp; </span><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><spa=
n 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> &n=
bsp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> beg=
in_impl</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">T </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">&</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">range</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><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">decltype</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">begin</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">range</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">))</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>  =
; </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">return</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">begi=
n</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">range</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><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br> </span><span style=3D"color: #80=
0;" class=3D"styled-by-prettify">// (3)</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br> </span><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">auto</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">begin</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">T </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">&</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">range</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: #6=
60;" 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-by-prettify">decltype</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">impl</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">begin=
_impl</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">range</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">))</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br> &n=
bsp; </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">return</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> impl</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">begin_impl</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">range</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: #660;" class=3D"st=
yled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span></div></code></div><br>(begin)(expression) is intended =
to be nearly equivalent to begin-expr in the range-based for statement<br><=
br> for (for-range-declaration : expression) statement<br=
><br>Unfortunately, this overload set doesn't work as intended, because (2)=
and (3) may produce equally viable specializations (so we'll get an ambigu=
ous call). We have to disable the ADL-based function when (2) would be viab=
le. This is possible with std::enable_if. Let's assume that we have a core =
language facility like this: <br><br> is_well_formed_expr=
ession(expr) =3D=3D true iff expr is a well-formed expression;<br> &nb=
sp; is_well_formed_expression(expr) =3D=3D false iff expr is an ill-f=
ormed expression.<br><br>Then we could define (3) as follows:<br><br><div c=
lass=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-=
color: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wra=
p: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">template</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">bool</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> C</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"> T </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">></span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br> &nb=
sp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">using<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> enable_if =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">typename</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">enable_if</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">C</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
>::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">type=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br><br> &nbs=
p; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">templat=
e</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span s=
tyle=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"colo=
r: #660;" class=3D"styled-by-prettify">></span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br> </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">begin</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" cla=
ss=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">range</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: #660;" class=3D"styled-by-prettify">-></spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> enable_if<br>&=
nbsp; </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br> &nbs=
p; </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
!</span><span style=3D"color: #000;" class=3D"styled-by-prettify">is_well_f=
ormed_expression</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">ran=
ge</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">begin</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">()),</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br> &nb=
sp; </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">decltype</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">impl</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
>begin_impl</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">range</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">))</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br> &nb=
sp; </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">></span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br> </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"style=
d-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> impl</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">be=
gin_impl</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">range</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">}</span></div></code></div><br>Al=
though this code doesn't look too complicated, someone could say that we ha=
ve a redundancy here: we need to duplicate a condition already expressed el=
sewhere. Let's modify the second template:<br><br><div class=3D"prettyprint=
" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187=
, 187); border-style: solid; border-width: 1px; word-wrap: break-word;"><co=
de class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">template</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify"><</span><span style=3D"color: #008;" clas=
s=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-b=
y-prettify">></span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br> </span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">begin</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">range</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">-></span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> enable_if<br>  =
; </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify"><</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br> std</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">::</span><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">decltype</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">range</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">.</span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">begin</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: #008;" class=3D"styled-by-prettify">declt=
ype</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">range</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">end</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">())>{}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br> &nbs=
p; </span><span style=3D"color: #008;" class=3D"styled=
-by-prettify">decltype</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">range</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.<=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">begin</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">())</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>  =
; </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">></span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br> </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-by=
-prettify">return</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> range</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">.</span><span style=3D"color: #008;" class=3D"styled-by-prettify">begin<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span></div></code></div><br>No=
w we have to change the third template accordingly:<br><br><div class=3D"pr=
ettyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb=
(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-w=
ord;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">template</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #0=
08;" 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"color: #000;" class=3D"style=
d-by-prettify"><br> </span><span style=3D"color:=
#008;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">begin</span><span style=3D"color: #660;" class=3D"s=
tyled-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">ran=
ge</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: #660;" class=3D"styled-by-prettify">-></span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> enable_if<br> &nb=
sp; </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br> </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">!</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">is_well_formed_expression=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">enable_if</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify"><</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">std</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">is_same</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify"><</span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">decltype</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">range</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">.</span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>begin</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()),=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">decltype</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">range</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">end</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">())>{}>()),</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br> &nb=
sp; </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">decltype</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">imp=
l</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">begin_impl</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">range</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">))</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"><br> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
; </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: #008;" class=3D"styled-by-prettify">retur=
n</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> impl</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify">begin_impl</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">range</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: #660;" class=
=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br></span></div></code></div><br>This doesn't look pretty, =
right? Alternatively, we could use is_well_formed_expression with static if=
and auto-deduced return types:<br><br><div class=3D"prettyprint" style=3D"=
background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bor=
der-style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D=
"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><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-p=
rettify"> T</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify">size_t </span><span st=
yle=3D"color: #606;" class=3D"styled-by-prettify">Size</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">></span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br> T </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">*</span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">begin</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">T </span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">(&</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">arr</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">)[</span><span style=3D"color: #606;" class=3D"styled-b=
y-prettify">Size</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">])</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> arr</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><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br><br> =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">namespace=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> impl<br>&=
nbsp; </span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&n=
bsp; </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">void</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>begin</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
</span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">template</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </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><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">></span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br> =
</span><span style=3D"color: #008;" class=3D"styled-by=
-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> begin_impl</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">(</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">range</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br> &nb=
sp; </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">return</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">begin</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">range</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"co=
lor: #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"><br> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br><br> </span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">template</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify"><</span><span style=3D"color: #008;" class=3D"s=
tyled-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-pret=
tify">></span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">begin</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">T </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">&</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify">range</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"><br> </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br> <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">static</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">is_well_formed_expression</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">enable_if</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">is_same</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify"><</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
decltype</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">range</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">begin</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">()),</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">decltype</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">range</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">.</span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">end</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
())>{}>())</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br> </span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br> </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">return</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> range</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">begin</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">();</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br> </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">else</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br> &n=
bsp; </span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nb=
sp; </span><span style=3D"color: #008;" =
class=3D"styled-by-prettify">return</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> impl</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">begin_impl</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">range</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br> </span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">}</span></div></code></div><br>This looks much better, however, =
I still would like to consider another approach.<br><br>Let's imagine that =
every function and function template have an associated value that represen=
ts the order in which the function or function template would be considered=
during overload resolution and we can explicitly specify the order using t=
he following syntax:<br><br> function-specifier:<br> =
; using [ constant-expression ]<br>&nbs=
p; ....<br><br>where the value of the c=
onstant-expression represents the order. If for a given function declaratio=
n or function template declaration the order is not specified explicitly, i=
t is implicitly assumed to be zero. Two declarations of the same function o=
r function template shall (implicitly or explicitly) assign the same order =
to the function. Currently I have no strong opinion about whether negative =
order values should be allowed.<br><br>Everytime when a set of candidate fu=
nctions is constructed for some context, the selection of the best function=
is performed as follows:<br><br>1. First, all candidate functions form a s=
et of remaining candidate functions; then<br><br>2. a subset of the remaini=
ng candidate functions with the minimal order is selected to form a set of =
currently considered candidate functions; then<br><br>3. a subset of the cu=
rrently considered candidate functions (those that have the proper number o=
f arguments and meet certain other conditions) is selected to form a set of=
viable functions; then<br><br>4. if the set of viable functions is empty, =
then currently considered candidate functions (determined in step 2) are ex=
cluded from the set of remaining candidate functions and if the resulting s=
et of remaining candidate functions is non-empty, steps 2 - 4 are performed=
again in order to re-evaluate the set of viable functions;<br><br>5. final=
ly, the best viable function is selected from the final set of viable funct=
ions according to 13.3.3. If a best viable function exists and is unique, o=
verload resolution succeeds and produces it as the result; otherwise overlo=
ad resolution fails.<br><br>Example:<br><br><div class=3D"prettyprint" styl=
e=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187)=
; border-style: solid; border-width: 1px; word-wrap: break-word;"><code cla=
ss=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">template</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify"><</span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">bool</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> C</span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><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 st=
yle=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">void</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">></span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">using</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> enable_if </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">typename</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">enable_if</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">C</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">>::</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">type</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br><br> </span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">// (1) order =3D 0</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br> </=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">template</sp=
an><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"c=
olor: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">></span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br> </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> f</span><span style=3D"color: =
#660;" 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-p=
rettify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
-></span><span style=3D"color: #000;" class=3D"styled-by-prettify"> enab=
le_if</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">is_signed</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">T</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">>{}>;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br><br> </span><span style=
=3D"color: #800;" class=3D"styled-by-prettify">// (2) order =3D 0</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br> </=
span><span style=3D"color: #008;" class=3D"styled-by-prettify">template</sp=
an><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"c=
olor: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">></span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br> </span><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">using</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">[</span><span style=3D"color=
: #066;" class=3D"styled-by-prettify">0</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-by=
-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> f</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">T</span><spa=
n 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><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> enable_if</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">is_floating_point</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify"><</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify">T</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">>{}>;</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br><br> </span><span style=3D"color: #800;" class=3D"sty=
led-by-prettify">// (3) order =3D 1</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br> </span><span style=3D"color: #00=
8;" 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"st=
yled-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-prett=
ify">></span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br> </span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">using</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">[</span><span style=3D"color: #066;" class=3D"styled-by-pre=
ttify">1</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: #008;" class=3D"styled-by-prettify">auto</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> f</span><span style=3D"co=
lor: #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"style=
d-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">-></span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> enable_if</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
><</span><span style=3D"color: #000;" class=3D"styled-by-prettify">std</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><sp=
an style=3D"color: #000;" 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"><br><br> </span><s=
pan style=3D"color: #800;" class=3D"styled-by-prettify">// (4) order =3D 1<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">tem=
plate</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: #008;" class=3D"styled-by-prettify">class</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">></span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"><br> </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">using</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">[</span><span style=3D=
"color: #066;" class=3D"styled-by-prettify">1</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">]</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> f</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">T</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">-></span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> enable_if</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">std</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">is_enum</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&g=
t;{}>;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br><br> </span><span style=3D"color: #800;" class=3D"styled-by=
-prettify">// (5) order =3D 2</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br> </span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">template</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify"><</span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">class</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> T</span><span style=3D"color: #660;" class=3D"styled-by-prettify">>=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
; </span><span style=3D"color: #008;" class=3D"styled-=
by-prettify">using</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">[</span><span style=3D"color: #066;" class=3D"styled-by-prettify">2=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">]</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> f</span><span style=3D"color: #66=
0;" 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"style=
d-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">-&g=
t;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> enable_=
if</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">is_scalar</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #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"><br><br> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> main</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">()</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br> </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br> </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">enum</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> e </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br><br> f</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #066;" cl=
ass=3D"styled-by-prettify">0</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// calls (1) [ {(1), (2)} =3D> (1) ]</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"><br> &nbs=
p; f</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>(</span><span style=3D"color: #066;" class=3D"styled-by-prettify">0.</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #800;" class=3D"styled-by-prettify">// calls (2) =
[ {(1), (2)} =3D> (2) ]</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br> f</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #066;"=
class=3D"styled-by-prettify">0u</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #800;" cl=
ass=3D"styled-by-prettify">// calls (3) [ {(1), (2)} =3D> none -> {(3=
), (4)} =3D> (3) ]</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br> f</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">e</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #800;" class=3D"=
styled-by-prettify">// calls (4) [ {(1), (2)} =3D> none -> {(3), (4)}=
=3D> (4) ]</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br> f</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">nullptr</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">//=
calls (5) [ {(1), (2)} =3D> none -> {(3), (4)} =3D> none -> {(=
5)} =3D> (5) ]</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">}</span></div></code></div><br>The definition of the ADL-bas=
ed 'begin' in the initial example could be changed to<br><br><div class=3D"=
prettyprint" style=3D"background-color: rgb(250, 250, 250); border-color: r=
gb(187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break=
-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> </span><span=
style=3D"color: #008;" class=3D"styled-by-prettify">template</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"c=
olor: #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"color: #000;" class=3D"st=
yled-by-prettify"><br> </span><span style=3D"col=
or: #008;" class=3D"styled-by-prettify">using</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">[</span><span style=3D"color: #066;" cla=
ss=3D"styled-by-prettify">1</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: #008;" class=3D"styled-by-prettify">a=
uto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">begin</span><spa=
n 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"colo=
r: #660;" class=3D"styled-by-prettify">&</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">range</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><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">dec=
ltype</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify">impl</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">begin_impl</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">range</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">))</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"><br> </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 style=3D"=
color: #008;" class=3D"styled-by-prettify">return</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> impl</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">begin_impl</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify">range</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</sp=
an></div></code></div><br>so it would not be considered unless the other tw=
o overloads are non-viable.<br><br>Other possible applications:<br><br>1)<b=
r><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250);=
border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; =
word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpretty=
print"><span style=3D"color: #000;" class=3D"styled-by-prettify"> &nb=
sp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">class<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> any<br>&nb=
sp; </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbs=
p; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
public</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> &n=
bsp; any</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">();</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br> any</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">any </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">const</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"><b=
r> any</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">any </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">&&);</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br> </span><span style=3D"color: #00=
8;" 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"st=
yled-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-prett=
ify">></span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br> </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">using</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">[</span><span style=3D"color: #066;" class=3D=
"styled-by-prettify">1</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">]</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> any</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify">T </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">&&);</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">};</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br><br> &nb=
sp; </span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"> main</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br> &n=
bsp; any a1</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-prettif=
y">// a1 is non-const</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"><br> any a2 </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> a1</span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pr=
ettify">// calls the copy ctor</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br> any a3 </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #06=
6;" class=3D"styled-by-prettify">0u</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pre=
ttify">// calls the template ctor</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">}</span></div></code></div><br>2)<br><div c=
lass=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250); border-=
color: rgb(187, 187, 187); border-style: solid; border-width: 1px; word-wra=
p: break-word;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">template</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D=
"color: #008;" class=3D"styled-by-prettify">class</span><span style=3D"colo=
r: #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"> </span><span style=3D"color: #008;" class=3D"style=
d-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"=
>Allocator</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> allocator</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"> </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">></span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">class</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> vector<br> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br> &n=
bsp; </span><span style=3D"color: #660;" class=3D"styled-by-prettify">....<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
vector</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">size_type n</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
T </span><span style=3D"color: #008;" class=3D"styled-by-prettify">const</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">&</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">value</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: #606;" cla=
ss=3D"styled-by-prettify">Allocator</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">const</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"> </=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Allocator</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">template</sp=
an><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"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #60=
6;" class=3D"styled-by-prettify">InputIterator</span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">></span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br> =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">using</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">[</span><span =
style=3D"color: #066;" class=3D"styled-by-prettify">1</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">]</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> vector</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">(</span><span style=3D"color: #606;" class=
=3D"styled-by-prettify">InputIterator</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> first</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-by-pret=
tify">InputIterator</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
last</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span s=
tyle=3D"color: #606;" class=3D"styled-by-prettify">Allocator</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">const</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">&</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">A=
llocator</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()=
);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>&nbs=
p; </span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">....</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">};</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"><br><br> </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">int</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> main</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br> vector</span><span style=3D"color: #080;" cl=
ass=3D"styled-by-prettify"><double></span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> v</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #066;" class=3D"style=
d-by-prettify">2</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: #066;" class=3D"styled-by-prettify">1</span><spa=
n 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">// calls the non-template ctor</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br> =
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><=
/div></code></div><br>3)<br><div class=3D"prettyprint" style=3D"background-=
color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: =
solid; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprin=
t"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">using</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">[</span><span style=3D"color: #066;" class=3D"styled-by-pret=
tify">1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">]</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #008;" class=3D"styled-by-prettify">void</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> f</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">char</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">const</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"> </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">{}</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br> </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">void</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> f</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">short</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">)</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: #000;" class=3D"styled-by-pre=
ttify"><br><br> </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">int</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> main</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: #660;" class=3D"styled-by-pre=
ttify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r> f</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">(</span><span style=3D"color: #066;" class=3D"styled-b=
y-prettify">0</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> &nbs=
p; </span><span style=3D"color: #800;" class=3D"styled-by-pre=
ttify">// calls f(short)</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"><br> f</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">nullptr</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pr=
ettify">// calls f(char const *)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br> </span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">}</span></div></code></div><br>Was a simila=
r feature ever suggested? Would it be significantly useful?<br>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_1585_609438.1357982902940--
.
Author: =?UTF-8?Q?R=C3=B3bert_D=C3=A1vid?= <lrdxgm@gmail.com>
Date: Sat, 12 Jan 2013 05:03:19 -0800 (PST)
Raw View
------=_Part_1464_4083169.1357995799737
Content-Type: text/plain; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
Hello,
I would like to point out that (2) and (3) in the first example are not=20
working not because they *may* produce equally viable specializations, but=
=20
because it is a violation of the One Definition Rule. They are both a=20
function called begin, with one templated parameter. Disabling ADL is not=
=20
enough.
The idea looks interesting, but my biggest issue is that with this=20
proposal, you look on a function, and you don't know what is the=20
parameter's type - there might or might not exists another function with=20
higher priority than this. Take number (3) in the last example: I, as a=20
programmer, have to know and see (1) and (2) (and extending that, I need to=
=20
see the *whole* translation unit) to know it will only be called for=20
unsigned integer types, and not all arithmetic ones.
I would like to know how would the is_well_formed_expression work, I see=20
potential in that.
Regards, Robert
2013. janu=E1r 12., szombat 10:28:22 UTC+1 id=F5pontban Nikolay Ivchenkov a=
=20
k=F6vetkez=F5t =EDrta:
>
> Sometimes a function from an overload set is supposed to be called only i=
f=20
> a certain subset of other candidates does not contain viable functions. F=
or=20
> example,
>
> // (1)
> template <class T, std::size_t Size>
> T *begin(T (&arr)[Size])
> { return arr; }
> // (2)
> template <class T>
> auto begin(T &range) -> decltype(range.begin())
> { return range.begin(); }
>
> namespace impl
> {
> void begin();
> template <class T>
> auto begin_impl(T &range) -> decltype(begin(range))
> { return begin(range); }
> }
> // (3)
> template <class T>
> auto begin(T &range) -> decltype(impl::begin_impl(range))
> { return impl::begin_impl(range); }
>
> (begin)(expression) is intended to be nearly equivalent to begin-expr in=
=20
> the range-based for statement
>
> for (for-range-declaration : expression) statement
>
> Unfortunately, this overload set doesn't work as intended, because (2) an=
d=20
> (3) may produce equally viable specializations (so we'll get an ambiguous=
=20
> call). We have to disable the ADL-based function when (2) would be viable=
..=20
> This is possible with std::enable_if. Let's assume that we have a core=20
> language facility like this:=20
>
> is_well_formed_expression(expr) =3D=3D true iff expr is a well-formed=
=20
> expression;
> is_well_formed_expression(expr) =3D=3D false iff expr is an ill-forme=
d=20
> expression.
>
> Then we could define (3) as follows:
>
> template <bool C, class T =3D void>
> using enable_if =3D typename std::enable_if<C, T>::type;
>
> template <class T>
> auto begin(T &range) -> enable_if
> <
> !is_well_formed_expression(range.begin()),
> decltype(impl::begin_impl(range))
> >
> { return impl::begin_impl(range); }
>
> Although this code doesn't look too complicated, someone could say that w=
e=20
> have a redundancy here: we need to duplicate a condition already expresse=
d=20
> elsewhere. Let's modify the second template:
>
> template <class T>
> auto begin(T &range) -> enable_if
> <
> std::is_same<decltype(range.begin()), decltype(range.end
> ())>{}
> decltype(range.begin())
> >
> { return range.begin(); }
>
> Now we have to change the third template accordingly:
>
> template <class T>
> auto begin(T &range) -> enable_if
> <
> !is_well_formed_expression(enable_if<std::is_same<decltyp=
e
> (range.begin()), decltype(range.end())>{}>()),
> decltype(impl::begin_impl(range))
> >
> { return impl::begin_impl(range); }
>
> This doesn't look pretty, right? Alternatively, we could use=20
> is_well_formed_expression with static if and auto-deduced return types:
>
> template <class T, std::size_t Size>
> T *begin(T (&arr)[Size])
> { return arr; }
>
> namespace impl
> {
> void begin();
> template <class T>
> auto begin_impl(T &range)
> { return begin(range); }
> }
>
> template <class T>
> auto begin(T &range)
> {
> static if (is_well_formed_expression(enable_if<std::is_same<
> decltype(range.begin()), decltype(range.end())>{}>())
> {
> return range.begin();
> }
> else
> {
> return impl::begin_impl(range);
> }
> }
>
> This looks much better, however, I still would like to consider another=
=20
> approach.
>
> Let's imagine that every function and function template have an associate=
d=20
> value that represents the order in which the function or function templat=
e=20
> would be considered during overload resolution and we can explicitly=20
> specify the order using the following syntax:
>
> function-specifier:
> using [ constant-expression ]
> ....
>
> where the value of the constant-expression represents the order. If for a=
=20
> given function declaration or function template declaration the order is=
=20
> not specified explicitly, it is implicitly assumed to be zero. Two=20
> declarations of the same function or function template shall (implicitly =
or=20
> explicitly) assign the same order to the function. Currently I have no=20
> strong opinion about whether negative order values should be allowed.
>
> Everytime when a set of candidate functions is constructed for some=20
> context, the selection of the best function is performed as follows:
>
> 1. First, all candidate functions form a set of remaining candidate=20
> functions; then
>
> 2. a subset of the remaining candidate functions with the minimal order i=
s=20
> selected to form a set of currently considered candidate functions; then
>
> 3. a subset of the currently considered candidate functions (those that=
=20
> have the proper number of arguments and meet certain other conditions) is=
=20
> selected to form a set of viable functions; then
>
> 4. if the set of viable functions is empty, then currently considered=20
> candidate functions (determined in step 2) are excluded from the set of=
=20
> remaining candidate functions and if the resulting set of remaining=20
> candidate functions is non-empty, steps 2 - 4 are performed again in orde=
r=20
> to re-evaluate the set of viable functions;
>
> 5. finally, the best viable function is selected from the final set of=20
> viable functions according to 13.3.3. If a best viable function exists an=
d=20
> is unique, overload resolution succeeds and produces it as the result;=20
> otherwise overload resolution fails.
>
> Example:
>
> template <bool C, class T =3D void>
> using enable_if =3D typename std::enable_if<C, T>::type;
>
> // (1) order =3D 0
> template <class T>
> auto f(T) -> enable_if<std::is_signed<T>{}>;
>
> // (2) order =3D 0
> template <class T>
> using[0] auto f(T) -> enable_if<std::is_floating_point<T>{}>;
>
> // (3) order =3D 1
> template <class T>
> using[1] auto f(T) -> enable_if<std::is_arithmetic<T>{}>;
>
> // (4) order =3D 1
> template <class T>
> using[1] auto f(T) -> enable_if<std::is_enum<T>{}>;
>
> // (5) order =3D 2
> template <class T>
> using[2]<span style=3D"color: #000;" class=3D"style...
> Eredeti megjelen=EDt=E9se<https://groups.google.com/a/isocpp.org/group/st=
d-proposals/msg/646541ee7a4e973?dmode=3Dsource&output=3Dgplain&noredirect>
>
--=20
------=_Part_1464_4083169.1357995799737
Content-Type: text/html; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable
Hello,<br><br>I would like to point out that (2) and (3) in the first examp=
le are not working not because they <i>may</i> produce equally viable speci=
alizations, but because it is a violation of the One Definition Rule. They =
are both a function called begin, with one templated parameter. Disabling A=
DL is not enough.<br><br>The idea looks interesting, but my biggest issue i=
s that with this proposal, you look on a function, and you don't know what =
is the parameter's type - there might or might not exists another function =
with higher priority than this. Take number (3) in the last example: I, as =
a programmer, have to know and see (1) and (2) (and extending that, I need =
to see the <b>whole</b> translation unit) to know it will only be called fo=
r unsigned integer types, and not all arithmetic ones.<br><br>I would like =
to know how would the <code><span style=3D"color:#000">is_well_formed_expre=
ssion</span><span style=3D"color:#660"></span></code> work, I see potential=
in that.<br><br>Regards, Robert<br><br>2013. janu=E1r 12., szombat 10:28:2=
2 UTC+1 id=F5pontban Nikolay Ivchenkov a k=F6vetkez=F5t =EDrta:<blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;">Sometimes a function from an overload set =
is supposed to be called only if a certain subset of other candidates does =
not contain viable functions. For example,<br><br><div style=3D"background-=
color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bor=
der-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#000">&=
nbsp; </span><span style=3D"color:#800">// (1)</span><span style=3D"=
color:#000"><br> </span><span style=3D"color:#008">template</s=
pan><span style=3D"color:#000"> </span><span style=3D"color:#660"><</spa=
n><span style=3D"color:#008">class</span><span style=3D"color:#000"> T</spa=
n><span style=3D"color:#660">,</span><span style=3D"color:#000"> std</span>=
<span style=3D"color:#660">::</span><span style=3D"color:#000">size_t </spa=
n><span style=3D"color:#606">Size</span><span style=3D"color:#660">></sp=
an><span style=3D"color:#000"><br> T </span><spa=
n style=3D"color:#660">*</span><span style=3D"color:#008">begin</span><span=
style=3D"color:#660">(</span><span style=3D"color:#000">T </span><span sty=
le=3D"color:#660">(&</span><span style=3D"color:#000">arr</span><span s=
tyle=3D"color:#660">)[</span><span style=3D"color:#606">Size</span><span st=
yle=3D"color:#660">])</span><span style=3D"color:#000"><br> &n=
bsp; </span><span style=3D"color:#660">{</span><span s=
tyle=3D"color:#000"> </span><span style=3D"color:#008">return</span><span s=
tyle=3D"color:#000"> arr</span><span style=3D"color:#660">;</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#660">}</span><span style=3D=
"color:#000"><br> </span><span style=3D"color:#800">// (2)</sp=
an><span style=3D"color:#000"><br> </span><span style=3D"color=
:#008">template</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#660"><</span><span style=3D"color:#008">class</span><span style=3D"c=
olor:#000"> T</span><span style=3D"color:#660">></span><span style=3D"co=
lor:#000"><br> </span><span style=3D"color:#008"=
>auto</span><span style=3D"color:#000"> </span><span style=3D"color:#008">b=
egin</span><span style=3D"color:#660">(</span><span style=3D"color:#000">T =
</span><span style=3D"color:#660">&</span><span style=3D"color:#000">ra=
nge</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </=
span><span style=3D"color:#660">-></span><span style=3D"color:#000"> </s=
pan><span style=3D"color:#008">decltype</span><span style=3D"color:#660">(<=
/span><span style=3D"color:#000">range</span><span style=3D"color:#660">.</=
span><span style=3D"color:#008">begin</span><span style=3D"color:#660">())<=
/span><span style=3D"color:#000"><br> &nb=
sp; </span><span style=3D"color:#660">{</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#008">return</span><span style=3D"color:#000"> r=
ange</span><span style=3D"color:#660">.</span><span style=3D"color:#008">be=
gin</span><span style=3D"color:#660">();</span><span style=3D"color:#000"> =
</span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br><b=
r> </span><span style=3D"color:#008">namespace</span><span sty=
le=3D"color:#000"> impl<br> </span><span style=3D"color:#660">=
{</span><span style=3D"color:#000"><br> </span><=
span style=3D"color:#008">void</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#008">begin</span><span style=3D"color:#660">();</span><s=
pan style=3D"color:#000"><br> </span><span style=
=3D"color:#008">template</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660"><</span><span style=3D"color:#008">class</span><span s=
tyle=3D"color:#000"> T</span><span style=3D"color:#660">></span><span st=
yle=3D"color:#000"><br> </span><sp=
an style=3D"color:#008">auto</span><span style=3D"color:#000"> begin_impl</=
span><span style=3D"color:#660">(</span><span style=3D"color:#000">T </span=
><span style=3D"color:#660">&</span><span style=3D"color:#000">range</s=
pan><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span><=
span style=3D"color:#660">-></span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#008">decltype</span><span style=3D"color:#660">(</span>=
<span style=3D"color:#008">begin</span><span style=3D"color:#660">(</span><=
span style=3D"color:#000">range</span><span style=3D"color:#660">))</span><=
span style=3D"color:#000"><br> &nb=
sp; </span><span style=3D"color:#660">{</span><span style=3D"color:#=
000"> </span><span style=3D"color:#008">return</span><span style=3D"color:#=
000"> </span><span style=3D"color:#008">begin</span><span style=3D"color:#6=
60">(</span><span style=3D"color:#000">range</span><span style=3D"color:#66=
0">);</span><span style=3D"color:#000"> </span><span style=3D"color:#660">}=
</span><span style=3D"color:#000"><br> </span><span style=3D"c=
olor:#660">}</span><span style=3D"color:#000"><br> </span><spa=
n style=3D"color:#800">// (3)</span><span style=3D"color:#000"><br> &=
nbsp; </span><span style=3D"color:#008">template</span><span style=3D"color=
:#000"> </span><span style=3D"color:#660"><</span><span style=3D"color:#=
008">class</span><span style=3D"color:#000"> T</span><span style=3D"color:#=
660">></span><span style=3D"color:#000"><br> =
</span><span style=3D"color:#008">auto</span><span style=3D"color:#000"> </=
span><span style=3D"color:#008">begin</span><span style=3D"color:#660">(</s=
pan><span style=3D"color:#000">T </span><span style=3D"color:#660">&</s=
pan><span style=3D"color:#000">range</span><span style=3D"color:#660">)</sp=
an><span style=3D"color:#000"> </span><span style=3D"color:#660">-></spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#008">decltype</s=
pan><span style=3D"color:#660">(</span><span style=3D"color:#000">impl</spa=
n><span style=3D"color:#660">::</span><span style=3D"color:#000">begin_impl=
</span><span style=3D"color:#660">(</span><span style=3D"color:#000">rang<w=
br>e</span><span style=3D"color:#660">))</span><span style=3D"color:#000"><=
br> </span><span style=3D"color:#6=
60">{</span><span style=3D"color:#000"> </span><span style=3D"color:#008">r=
eturn</span><span style=3D"color:#000"> impl</span><span style=3D"color:#66=
0">::</span><span style=3D"color:#000">begin_impl</span><span style=3D"colo=
r:#660">(</span><span style=3D"color:#000">range</span><span style=3D"color=
:#660">);</span><span style=3D"color:#000"> </span><span style=3D"color:#66=
0">}</span><span style=3D"color:#000"><br></span></div></code></div><br>(be=
gin)(expression) is intended to be nearly equivalent to begin-expr in the r=
ange-based for statement<br><br> for (for-range-declarati=
on : expression) statement<br><br>Unfortunately, this overload set doesn't =
work as intended, because (2) and (3) may produce equally viable specializa=
tions (so we'll get an ambiguous call). We have to disable the ADL-based fu=
nction when (2) would be viable. This is possible with std::enable_if. Let'=
s assume that we have a core language facility like this: <br><br> &nb=
sp; is_well_formed_expression(<wbr>expr) =3D=3D true iff expr is a we=
ll-formed expression;<br> is_well_formed_expression(<wbr>=
expr) =3D=3D false iff expr is an ill-formed expression.<br><br>Then we cou=
ld define (3) as follows:<br><br><div style=3D"background-color:rgb(250,250=
,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px;wor=
d-wrap:break-word"><code><div><span style=3D"color:#000"> </sp=
an><span style=3D"color:#008">template</span><span style=3D"color:#000"> </=
span><span style=3D"color:#660"><</span><span style=3D"color:#008">bool<=
/span><span style=3D"color:#000"> C</span><span style=3D"color:#660">,</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#008">class</span=
><span style=3D"color:#000"> T </span><span style=3D"color:#660">=3D</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#008">void</span><s=
pan style=3D"color:#660">></span><span style=3D"color:#000"><br> &=
nbsp; </span><span style=3D"color:#008">using</span><span sty=
le=3D"color:#000"> enable_if </span><span style=3D"color:#660">=3D</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#008">typename</span>=
<span style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><=
span style=3D"color:#000">enable_if</span><span style=3D"color:#660"><</=
span><span style=3D"color:#000">C</span><span style=3D"color:#660">,</span>=
<span style=3D"color:#000"> T</span><span style=3D"color:#660">>::</span=
><span style=3D"color:#000">type</span><span style=3D"color:#660">;</span><=
span style=3D"color:#000"><br><br> </span><span style=3D"color=
:#008">template</span><span style=3D"color:#000"> </span><span style=3D"col=
or:#660"><</span><span style=3D"color:#008">class</span><span style=3D"c=
olor:#000"> T</span><span style=3D"color:#660">></span><span style=3D"co=
lor:#000"><br> </span><span style=3D"color:#008"=
>auto</span><span style=3D"color:#000"> </span><span style=3D"color:#008">b=
egin</span><span style=3D"color:#660">(</span><span style=3D"color:#000">T =
</span><span style=3D"color:#660">&</span><span style=3D"color:#000">ra=
nge</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </=
span><span style=3D"color:#660">-></span><span style=3D"color:#000"> ena=
ble_if<br> </span><span style=3D"c=
olor:#660"><</span><span style=3D"color:#000"><br> &=
nbsp; </span><span style=3D"color:#660">!</span=
><span style=3D"color:#000">is_well_formed_expression</span><span style=3D"=
color:#660">(</span><span style=3D"color:#000">ran<wbr>ge</span><span style=
=3D"color:#660">.</span><span style=3D"color:#008">begin</span><span style=
=3D"color:#660">()),</span><span style=3D"color:#000"><br> &nb=
sp; </span><span style=3D"color:#008">de=
cltype</span><span style=3D"color:#660">(</span><span style=3D"color:#000">=
impl</span><span style=3D"color:#660">::</span><span style=3D"color:#000">b=
egin_impl</span><span style=3D"color:#660">(</span><span style=3D"color:#00=
0">rang<wbr>e</span><span style=3D"color:#660">))</span><span style=3D"colo=
r:#000"><br> </span><span style=3D=
"color:#660">></span><span style=3D"color:#000"><br> =
</span><span style=3D"color:#660">{</span><span style=3D"color:#000=
"> </span><span style=3D"color:#008">return</span><span style=3D"color:#000=
"> impl</span><span style=3D"color:#660">::</span><span style=3D"color:#000=
">begin_impl</span><span style=3D"color:#660">(</span><span style=3D"color:=
#000">range</span><span style=3D"color:#660">);</span><span style=3D"color:=
#000"> </span><span style=3D"color:#660">}</span></div></code></div><br>Alt=
hough this code doesn't look too complicated, someone could say that we hav=
e a redundancy here: we need to duplicate a condition already expressed els=
ewhere. Let's modify the second template:<br><br><div style=3D"background-c=
olor:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bord=
er-width:1px;word-wrap:break-word"><code><div><span style=3D"color:#000">&n=
bsp; </span><span style=3D"color:#008">template</span><span style=3D=
"color:#000"> </span><span style=3D"color:#660"><</span><span style=3D"c=
olor:#008">class</span><span style=3D"color:#000"> T</span><span style=3D"c=
olor:#660">></span><span style=3D"color:#000"><br> &=
nbsp; </span><span style=3D"color:#008">auto</span><span style=3D"color:#00=
0"> </span><span style=3D"color:#008">begin</span><span style=3D"color:#660=
">(</span><span style=3D"color:#000">T </span><span style=3D"color:#660">&a=
mp;</span><span style=3D"color:#000">range</span><span style=3D"color:#660"=
>)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">->=
;</span><span style=3D"color:#000"> enable_if<br>  =
; </span><span style=3D"color:#660"><</span><span style=3D=
"color:#000"><br> st=
d</span><span style=3D"color:#660">::</span><span style=3D"color:#000">is_s=
ame</span><span style=3D"color:#660"><</span><span style=3D"color:#008">=
decltype</span><span style=3D"color:#660">(</span><span style=3D"color:#000=
">range</span><span style=3D"color:#660">.</span><span style=3D"color:#008"=
>be<wbr>gin</span><span style=3D"color:#660">()),</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#008">decltype</span><span style=3D"co=
lor:#660">(</span><span style=3D"color:#000">range</span><span style=3D"col=
or:#660">.</span><span style=3D"color:#008">end</span><span style=3D"color:=
#660">())>{}</span><span style=3D"color:#000"><br> &=
nbsp; </span><span style=3D"color:#008">decltyp=
e</span><span style=3D"color:#660">(</span><span style=3D"color:#000">range=
</span><span style=3D"color:#660">.</span><span style=3D"color:#008">begin<=
/span><span style=3D"color:#660">())</span><span style=3D"color:#000"><br>&=
nbsp; </span><span style=3D"color:#660">=
></span><span style=3D"color:#000"><br> </spa=
n><span style=3D"color:#660">{</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#008">return</span><span style=3D"color:#000"> range</spa=
n><span style=3D"color:#660">.</span><span style=3D"color:#008">begin</span=
><span style=3D"color:#660">();</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#660">}</span><span style=3D"color:#000"><br></span></di=
v></code></div><br>Now we have to change the third template accordingly:<br=
><br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,1=
87,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><di=
v><span style=3D"color:#000"> </span><span style=3D"color:#008=
">template</span><span style=3D"color:#000"> </span><span style=3D"color:#6=
60"><</span><span style=3D"color:#008">class</span><span style=3D"color:=
#000"> T</span><span style=3D"color:#660">></span><span style=3D"color:#=
000"><br> </span><span style=3D"color:#008">auto=
</span><span style=3D"color:#000"> </span><span style=3D"color:#008">begin<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#000">T </spa=
n><span style=3D"color:#660">&</span><span style=3D"color:#000">range</=
span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span>=
<span style=3D"color:#660">-></span><span style=3D"color:#000"> enable_i=
f<br> </span><span style=3D"color:=
#660"><</span><span style=3D"color:#000"><br> =
</span><span style=3D"color:#660">!</span><spa=
n style=3D"color:#000">is_well_formed_expression</span><span style=3D"color=
:#660">(</span><span style=3D"color:#000">ena<wbr>ble_if</span><span style=
=3D"color:#660"><</span><span style=3D"color:#000">std</span><span style=
=3D"color:#660">::</span><span style=3D"color:#000">is_same</span><span sty=
le=3D"color:#660"><</span><span style=3D"color:#008">decltype</span><spa=
n style=3D"color:#660">(</span><span style=3D"color:#000">r<wbr>ange</span>=
<span style=3D"color:#660">.</span><span style=3D"color:#008">begin</span><=
span style=3D"color:#660">()),</span><span style=3D"color:#000"> </span><sp=
an style=3D"color:#008">decltype</span><span style=3D"color:#660">(</span><=
span style=3D"color:#000">range</span><span style=3D"color:#660">.</span><s=
pan style=3D"color:#008">end</span><span style=3D"color:#660">())>{}>=
()),</span><span style=3D"color:#000"><br>  =
; </span><span style=3D"color:#008">decltype</span><sp=
an style=3D"color:#660">(</span><span style=3D"color:#000">impl</span><span=
style=3D"color:#660">::</span><span style=3D"color:#000">begin_impl</span>=
<span style=3D"color:#660">(</span><span style=3D"color:#000">rang<wbr>e</s=
pan><span style=3D"color:#660">))</span><span style=3D"color:#000"><br>&nbs=
p; </span><span style=3D"color:#660">>=
;</span><span style=3D"color:#000"><br> </span><=
span style=3D"color:#660">{</span><span style=3D"color:#000"> </span><span =
style=3D"color:#008">return</span><span style=3D"color:#000"> impl</span><s=
pan style=3D"color:#660">::</span><span style=3D"color:#000">begin_impl</sp=
an><span style=3D"color:#660">(</span><span style=3D"color:#000">range</spa=
n><span style=3D"color:#660">);</span><span style=3D"color:#000"> </span><s=
pan style=3D"color:#660">}</span><span style=3D"color:#000"><br></span></di=
v></code></div><br>This doesn't look pretty, right? Alternatively, we could=
use is_well_formed_expression with static if and auto-deduced return types=
:<br><br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(1=
87,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><code=
><div><span style=3D"color:#000"> </span><span style=3D"color:=
#008">template</span><span style=3D"color:#000"> </span><span style=3D"colo=
r:#660"><</span><span style=3D"color:#008">class</span><span style=3D"co=
lor:#000"> T</span><span style=3D"color:#660">,</span><span style=3D"color:=
#000"> std</span><span style=3D"color:#660">::</span><span style=3D"color:#=
000">size_t </span><span style=3D"color:#606">Size</span><span style=3D"col=
or:#660">></span><span style=3D"color:#000"><br> &nb=
sp; T </span><span style=3D"color:#660">*</span><span style=3D"color:#008">=
begin</span><span style=3D"color:#660">(</span><span style=3D"color:#000">T=
</span><span style=3D"color:#660">(&</span><span style=3D"color:#000">=
arr</span><span style=3D"color:#660">)[</span><span style=3D"color:#606">Si=
ze</span><span style=3D"color:#660">])</span><span style=3D"color:#000"><br=
> </span><span style=3D"color:#660=
">{</span><span style=3D"color:#000"> </span><span style=3D"color:#008">ret=
urn</span><span style=3D"color:#000"> arr</span><span style=3D"color:#660">=
;</span><span style=3D"color:#000"> </span><span style=3D"color:#660">}</sp=
an><span style=3D"color:#000"><br><br> </span><span style=3D"c=
olor:#008">namespace</span><span style=3D"color:#000"> impl<br>  =
; </span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#008">void</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#008">begin</span><sp=
an style=3D"color:#660">();</span><span style=3D"color:#000"><br> &nb=
sp; </span><span style=3D"color:#008">template</span><span st=
yle=3D"color:#000"> </span><span style=3D"color:#660"><</span><span styl=
e=3D"color:#008">class</span><span style=3D"color:#000"> T</span><span styl=
e=3D"color:#660">></span><span style=3D"color:#000"><br> &n=
bsp; </span><span style=3D"color:#008">auto</span><spa=
n style=3D"color:#000"> begin_impl</span><span style=3D"color:#660">(</span=
><span style=3D"color:#000">T </span><span style=3D"color:#660">&</span=
><span style=3D"color:#000">range</span><span style=3D"color:#660">)</span>=
<span style=3D"color:#000"><br> &n=
bsp; </span><span style=3D"color:#660">{</span><span style=3D"color:=
#000"> </span><span style=3D"color:#008">return</span><span style=3D"color:=
#000"> </span><span style=3D"color:#008">begin</span><span style=3D"color:#=
660">(</span><span style=3D"color:#000">range</span><span style=3D"color:#6=
60">);</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
}</span><span style=3D"color:#000"><br> </span><span style=3D"=
color:#660">}</span><span style=3D"color:#000"><br><br> </span=
><span style=3D"color:#008">template</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#660"><</span><span style=3D"color:#008">class</=
span><span style=3D"color:#000"> T</span><span style=3D"color:#660">></s=
pan><span style=3D"color:#000"><br> </span><span=
style=3D"color:#008">auto</span><span style=3D"color:#000"> </span><span s=
tyle=3D"color:#008">begin</span><span style=3D"color:#660">(</span><span st=
yle=3D"color:#000">T </span><span style=3D"color:#660">&</span><span st=
yle=3D"color:#000">range</span><span style=3D"color:#660">)</span><span sty=
le=3D"color:#000"><br> </span><span style=3D"color:#660">{</sp=
an><span style=3D"color:#000"><br> </span><span =
style=3D"color:#008">static</span><span style=3D"color:#000"> </span><span =
style=3D"color:#008">if</span><span style=3D"color:#000"> </span><span styl=
e=3D"color:#660">(</span><span style=3D"color:#000">is_well_formed_expressi=
on</span><span style=3D"color:#660">(</span><span style=3D"color:#000">ena<=
wbr>ble_if</span><span style=3D"color:#660"><</span><span style=3D"color=
:#000">std</span><span style=3D"color:#660">::</span><span style=3D"color:#=
000">is_same</span><span style=3D"color:#660"><</span><span style=3D"col=
or:#008">decltype</span><span style=3D"color:#660">(</span><span style=3D"c=
olor:#000">r<wbr>ange</span><span style=3D"color:#660">.</span><span style=
=3D"color:#008">begin</span><span style=3D"color:#660">()),</span><span sty=
le=3D"color:#000"> </span><span style=3D"color:#008">decltype</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#000">range</span><span st=
yle=3D"color:#660">.</span><span style=3D"color:#008">end</span><span style=
=3D"color:#660">())>{}>())</span><span style=3D"color:#000"><br> =
; </span><span style=3D"color:#660">{</span><span styl=
e=3D"color:#000"><br> </span><span=
style=3D"color:#008">return</span><span style=3D"color:#000"> range</span>=
<span style=3D"color:#660">.</span><span style=3D"color:#008">begin</span><=
span style=3D"color:#660">();</span><span style=3D"color:#000"><br> &=
nbsp; </span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br> </span><span style=3D"color=
:#008">else</span><span style=3D"color:#000"><br>  =
; </span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#008"=
>return</span><span style=3D"color:#000"> impl</span><span style=3D"color:#=
660">::</span><span style=3D"color:#000">begin_impl</span><span style=3D"co=
lor:#660">(</span><span style=3D"color:#000">range</span><span style=3D"col=
or:#660">);</span><span style=3D"color:#000"><br>  =
; </span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#660">}</span></div></code></div>=
<br>This looks much better, however, I still would like to consider another=
approach.<br><br>Let's imagine that every function and function template h=
ave an associated value that represents the order in which the function or =
function template would be considered during overload resolution and we can=
explicitly specify the order using the following syntax:<br><br> &nbs=
p; function-specifier:<br> =
using [ constant-expression ]<br> =
....<br><br>where the value of the constant-expression represents the orde=
r. If for a given function declaration or function template declaration the=
order is not specified explicitly, it is implicitly assumed to be zero. Tw=
o declarations of the same function or function template shall (implicitly =
or explicitly) assign the same order to the function. Currently I have no s=
trong opinion about whether negative order values should be allowed.<br><br=
>Everytime when a set of candidate functions is constructed for some contex=
t, the selection of the best function is performed as follows:<br><br>1. Fi=
rst, all candidate functions form a set of remaining candidate functions; t=
hen<br><br>2. a subset of the remaining candidate functions with the minima=
l order is selected to form a set of currently considered candidate functio=
ns; then<br><br>3. a subset of the currently considered candidate functions=
(those that have the proper number of arguments and meet certain other con=
ditions) is selected to form a set of viable functions; then<br><br>4. if t=
he set of viable functions is empty, then currently considered candidate fu=
nctions (determined in step 2) are excluded from the set of remaining candi=
date functions and if the resulting set of remaining candidate functions is=
non-empty, steps 2 - 4 are performed again in order to re-evaluate the set=
of viable functions;<br><br>5. finally, the best viable function is select=
ed from the final set of viable functions according to 13.3.3. If a best vi=
able function exists and is unique, overload resolution succeeds and produc=
es it as the result; otherwise overload resolution fails.<br><br>Example:<b=
r><br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,=
187,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><d=
iv><span style=3D"color:#000"> </span><span style=3D"color:#00=
8">template</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660"><</span><span style=3D"color:#008">bool</span><span style=3D"color:=
#000"> C</span><span style=3D"color:#660">,</span><span style=3D"color:#000=
"> </span><span style=3D"color:#008">class</span><span style=3D"color:#000"=
> T </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000">=
</span><span style=3D"color:#008">void</span><span style=3D"color:#660">&g=
t;</span><span style=3D"color:#000"><br> </span>=
<span style=3D"color:#008">using</span><span style=3D"color:#000"> enable_i=
f </span><span style=3D"color:#660">=3D</span><span style=3D"color:#000"> <=
/span><span style=3D"color:#008">typename</span><span style=3D"color:#000">=
std</span><span style=3D"color:#660">::</span><span style=3D"color:#000">e=
nable_if</span><span style=3D"color:#660"><</span><span style=3D"color:#=
000">C</span><span style=3D"color:#660">,</span><span style=3D"color:#000">=
T</span><span style=3D"color:#660">>::</span><span style=3D"color:#000"=
>type</span><span style=3D"color:#660">;</span><span style=3D"color:#000"><=
br><br> </span><span style=3D"color:#800">// (1) order =3D 0</=
span><span style=3D"color:#000"><br> </span><span style=3D"col=
or:#008">template</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#660"><</span><span style=3D"color:#008">class</span><span style=3D=
"color:#000"> T</span><span style=3D"color:#660">></span><span style=3D"=
color:#000"><br> </span><span style=3D"color:#00=
8">auto</span><span style=3D"color:#000"> f</span><span style=3D"color:#660=
">(</span><span style=3D"color:#000">T</span><span style=3D"color:#660">)</=
span><span style=3D"color:#000"> </span><span style=3D"color:#660">-></s=
pan><span style=3D"color:#000"> enable_if</span><span style=3D"color:#660">=
<</span><span style=3D"color:#000">std</span><span style=3D"color:#660">=
::</span><span style=3D"color:#000">is_signed</span><span style=3D"color:#6=
60"><</span><span style=3D"color:#000">T</span><span style=3D"color:#660=
">>{}><wbr>;</span><span style=3D"color:#000"><br><br> <=
/span><span style=3D"color:#800">// (2) order =3D 0</span><span style=3D"co=
lor:#000"><br> </span><span style=3D"color:#008">template</spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#660"><</span>=
<span style=3D"color:#008">class</span><span style=3D"color:#000"> T</span>=
<span style=3D"color:#660">></span><span style=3D"color:#000"><br> =
</span><span style=3D"color:#008">using</span><span s=
tyle=3D"color:#660">[</span><span style=3D"color:#066">0</span><span style=
=3D"color:#660">]</span><span style=3D"color:#000"> </span><span style=3D"c=
olor:#008">auto</span><span style=3D"color:#000"> f</span><span style=3D"co=
lor:#660">(</span><span style=3D"color:#000">T</span><span style=3D"color:#=
660">)</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
-></span><span style=3D"color:#000"> enable_if</span><span style=3D"colo=
r:#660"><</span><span style=3D"color:#000">std</span><span style=3D"colo=
r:#660">::</span><span style=3D"color:#000">is_floating_<wbr>point</span><s=
pan style=3D"color:#660"><</span><span style=3D"color:#000">T</span><spa=
n style=3D"color:#660">>{}>;</span><span style=3D"color:#000"><br><br=
> </span><span style=3D"color:#800">// (3) order =3D 1</span><=
span style=3D"color:#000"><br> </span><span style=3D"color:#00=
8">template</span><span style=3D"color:#000"> </span><span style=3D"color:#=
660"><</span><span style=3D"color:#008">class</span><span style=3D"color=
:#000"> T</span><span style=3D"color:#660">></span><span style=3D"color:=
#000"><br> </span><span style=3D"color:#008">usi=
ng</span><span style=3D"color:#660">[</span><span style=3D"color:#066">1</s=
pan><span style=3D"color:#660">]</span><span style=3D"color:#000"> </span><=
span style=3D"color:#008">auto</span><span style=3D"color:#000"> f</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#000">T</span><span s=
tyle=3D"color:#660">)</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">-></span><span style=3D"color:#000"> enable_if</span><sp=
an style=3D"color:#660"><</span><span style=3D"color:#000">std</span><sp=
an style=3D"color:#660">::</span><span style=3D"color:#000">is_arithmetic</=
span><span style=3D"color:#660"><</span><span style=3D"color:#000">T</sp=
an><span style=3D"color:#660"><wbr>>{}>;</span><span style=3D"color:#=
000"><br><br> </span><span style=3D"color:#800">// (4) order =
=3D 1</span><span style=3D"color:#000"><br> </span><span style=
=3D"color:#008">template</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660"><</span><span style=3D"color:#008">class</span><span s=
tyle=3D"color:#000"> T</span><span style=3D"color:#660">></span><span st=
yle=3D"color:#000"><br> </span><span style=3D"co=
lor:#008">using</span><span style=3D"color:#660">[</span><span style=3D"col=
or:#066">1</span><span style=3D"color:#660">]</span><span style=3D"color:#0=
00"> </span><span style=3D"color:#008">auto</span><span style=3D"color:#000=
"> f</span><span style=3D"color:#660">(</span><span style=3D"color:#000">T<=
/span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </span=
><span style=3D"color:#660">-></span><span style=3D"color:#000"> enable_=
if</span><span style=3D"color:#660"><</span><span style=3D"color:#000">s=
td</span><span style=3D"color:#660">::</span><span style=3D"color:#000">is_=
enum</span><span style=3D"color:#660"><</span><span style=3D"color:#000"=
>T</span><span style=3D"color:#660">>{}>;</span><span style=3D"color:=
#000"><br><br> </span><span style=3D"color:#800">// (5) order =
=3D 2</span><span style=3D"color:#000"><br> </span><span style=
=3D"color:#008">template</span><span style=3D"color:#000"> </span><span sty=
le=3D"color:#660"><</span><span style=3D"color:#008">class</span><span s=
tyle=3D"color:#000"> T</span><span style=3D"color:#660">></span><span st=
yle=3D"color:#000"><br> </span><span style=3D"co=
lor:#008">using</span><span style=3D"color:#660">[</span><span style=3D"col=
or:#066">2</span><span style=3D"color:#660">]</span><span style=3D"color=
: #000;" class=3D"style...<br><a href=3D"https://groups.google.com/a/isocpp=
..org/group/std-proposals/msg/646541ee7a4e973?dmode=3Dsource&output=3Dgp=
lain&noredirect" target=3D"_blank">Eredeti megjelen=EDt=E9se</a></div><=
/code></div></blockquote>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_1464_4083169.1357995799737--
.
Author: Nikolay Ivchenkov <tsoae@mail.ru>
Date: Sat, 12 Jan 2013 07:00:07 -0800 (PST)
Raw View
------=_Part_382_20542745.1358002807947
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Saturday, January 12, 2013 5:03:19 PM UTC+4, R=F3bert D=E1vid wrote:
>
> Hello,
>
> I would like to point out that (2) and (3) in the first example are not=
=20
> working not because they *may* produce equally viable specializations,=20
> but because it is a violation of the One Definition Rule. They are both a=
=20
> function called begin, with one templated parameter. Disabling ADL is not=
=20
> enough.
>
The signature of a function template includes its return type - see 1.3.18.=
=20
Templates (2) and (3) have different return types, thus they are different=
=20
templates. I don't see any problems with ODR here.
=20
> The idea looks interesting, but my biggest issue is that with this=20
> proposal, you look on a function, and you don't know what is the=20
> parameter's type - there might or might not exists another function with=
=20
> higher priority than this. Take number (3) in the last example: I, as a=
=20
> programmer, have to know and see (1) and (2) (and extending that, I need =
to=20
> see the *whole* translation unit) to know it will only be called for=20
> unsigned integer types, and not all arithmetic ones.
>
I think that this is not a new issue. For example, here
struct string_ref
{
string_ref(char const *first, char const *ending =3D nullptr);
};
void output(string_ref s);
int main()
{
output("string");
}
we can't determine whether output(string_ref s) is actually called if we=20
don't see preceding lines. There may exist a prior declaration
void output(bool b);
then the overload resolution would select output(bool b) instead of=20
output(string_ref s).
I would like to know how would the is_well_formed_expression work, I see=20
> potential in that.
>
It could work like SFINAE: if the operand is semantically invalid, that's=
=20
not a hard error, the operator just returns false. Such an operator could=
=20
be named as is_well_formed and be applicable to types as well. Currently we=
=20
can't implement such a thing as a macro that could be used as shown above.=
=20
However, a similar effect can be achieved with auxiliary declarations:
http://liveworkspace.org/code/828Wn$0
Here we first declare the expression pattern std::declval<T>().begin()=20
where T is an unknown type. Then the exact expression can specified by a=20
pair of the pattern and an argument for T, so, for instance,
IS_VALID_EXPRESSION(has_member_begin, std::vector<int>)
checks whether expression std::declval<std::vector<int>>().begin() is=20
well-formed.
--=20
------=_Part_382_20542745.1358002807947
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Saturday, January 12, 2013 5:03:19 PM UTC+4, R=F3bert D=E1vid wrote:<blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;">Hello,<br><br>I would like to poin=
t out that (2) and (3) in the first example are not working not because the=
y <i>may</i> produce equally viable specializations, but because it is a vi=
olation of the One Definition Rule. They are both a function called begin, =
with one templated parameter. Disabling ADL is not enough.<br></blockquote>=
<div><br>The signature of a function template includes its return type - se=
e 1.3.18. Templates (2) and (3) have different return types, thus they are =
different templates. I don't see any problems with ODR here.<br> </div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;">The idea looks interesting, b=
ut my biggest issue is that with this proposal, you look on a function, and=
you don't know what is the parameter's type - there might or might not exi=
sts another function with higher priority than this. Take number (3) in the=
last example: I, as a programmer, have to know and see (1) and (2) (and ex=
tending that, I need to see the <b>whole</b> translation unit) to know it w=
ill only be called for unsigned integer types, and not all arithmetic ones.=
<br></blockquote><div><br>I think that this is not a new issue. For example=
, here<br><br> struct string_ref<br> {<=
br> string_ref(char const *first,=
char const *ending =3D nullptr);<br> };<br><br> &nb=
sp; void output(string_ref s);<br><br> int main()<b=
r> {<br> output=
("string");<br> }<br><br>we can't determine whether outpu=
t(string_ref s) is actually called if we don't see preceding lines. There m=
ay exist a prior declaration<br><br> void output(bool b);=
<br><br>then the overload resolution would select output(bool b) instead of=
output(string_ref s).<br><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;">I would like to know how would the <code><span style=3D"color:#000">i=
s_well_formed_expression</span><span style=3D"color:#660"></span></code> wo=
rk, I see potential in that.<br></blockquote><div><br>It could work like SF=
INAE: if the operand is semantically invalid, that's not a hard error, the =
operator just returns false. Such an operator could be named as is_well_for=
med and be applicable to types as well. Currently we can't implement such a=
thing as a macro that could be used as shown above. However, a similar eff=
ect can be achieved with auxiliary declarations:<br><br>http://liveworkspac=
e.org/code/828Wn$0<br><br>Here we first declare the expression pattern std:=
:declval<T>().begin() where T is an unknown type. Then the exact expr=
ession can specified by a pair of the pattern and an argument for T, so, fo=
r instance,<br><br> IS_VALID_EXPRESSION(has_member_begin,=
std::vector<int>)<br><br>checks whether expression std::declval<s=
td::vector<int>>().begin() is well-formed.<br></div>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_382_20542745.1358002807947--
.