Topic: Ability to access the position of a type while
Author: scovich@gmail.com
Date: Mon, 20 Jul 2015 11:08:38 -0700 (PDT)
Raw View
------=_Part_5285_2072225703.1437415718860
Content-Type: multipart/alternative;
boundary="----=_Part_5286_1522603086.1437415718862"
------=_Part_5286_1522603086.1437415718862
Content-Type: text/plain; charset=UTF-8
Hi,
Variadic template parameters are really nice, and it's really impressive
how complex of expressions you can unpack (with more coming once C++17
allows folds). However, there is currently a glaring gap in the feature:
you can't access the position number of a type when unpacking a parameter
pack. This makes it unnecessarily hard to write code that mixes parameter
packs and tuples, because the one works with variadic lists of types and
the other requires use of std::get<size_t>.
The idea I'd like to float, then, is that the position of a given type
within its pack should be accessible during unpacking:
template <typename...Ts>
std::vector<size_t> foo(Ts&& ...) { return {#Ts...}; }
int main() {
std::vector a{0,1,2}, b=foo("hi", "ho", "hum");
assert(a == b); // succeeds
}
The above function is clearly a toy example, and the exact syntax need not
be '#Ts' but hopefully it conveys the idea. The feature would complement
the existing sizeof...() operator, and I do not think it would be difficult
to provide compiler support for it (though I am by no means a compiler
expert).
The rest of this message consists of examples to show why such a syntax
might be useful. The first three examples were extracted from real-life
scenarios I encountered in my work, though they have been simplified
drastically here to be more concise. The last example I made up, to show
something that would be really unpleasant to express without the proposed
syntax.
Apologies in advance if this idea has already been floated in the past---a
search of this forum did not turn up any obvious matches, but that doesn't
mean much.
Example 1:
====================
Suppose I have some code that assigns values to a std::tuple which are
constructible and assignable---but not convertible---to the tuple's field
types. This means I can't write this:
template <typename T>
struct StoredType { using type=T; };
/* various specializations of StoredType follow, but
* std::is_constructible<StoredType<T>::type, T> always holds
*/
template <typename... FTs>
struct Foo {
std::tuple<typename StoredType<FTs>::type...> _data;
Foo(FTs const & ...args) : _data{args...} { } // error!
};
Instead, the constructor needs a hack like the following:
Foo(FTs const & ...args) { init_data<0,FTs...>(args...); }
template <size_t M, typename T, typename... Rest>
void init_data(T const &arg, Rest const & ...rest) {
std::get<M>(_data) = arg;
init_data<M+1, Rest...>(rest...);
}
template <size_t M, typename T>
void init_data(T const &arg) {
std::get<M>(_data) = arg;
}
If there were a way to access type positions in a parameter pack, the
constructor hack would be much simpler and cleaner:
Foo(FTs const & ...args) {
auto x = {(std::get<#FTs>(_data)=args)...};
(void) x;
}
(I know that N4387 will address this particular problem, but that's besides
the point)
Example 2:
====================
Consider a fold function that accepts some number of inputs and applies an
action to each of them (vaguely similar to what C++17 is likely to
support). If the values to be folded are provided as arguments to a
variadic template function, then it's really easy (assuming C++14 generic
lambdas):
// workaround for fact that we can't make a std::initializer_list<void>
template <typename Action, typename T>
bool void_fold_one(Action &action, T &&t) {
action(std::forward<T>(t));
return true;
}
template <typename Action, typename T, typename... Ts>
void void_fold(Action &&action, T &&t, Ts&&... args)
{
auto x = {void_fold_one(action, std::forward<T>(t))...};
(void) x;
}
int main() {
auto action = [](auto x) { std::cout << x << " "; };
void_fold(action, 1, 3.14, "hi", std::endl);
}
Now try to do that with a std::tuple instead and you end up with something
much less satisfying:
template <size_t I, size_t N>
struct void_fold_tuple_ {
template <typename Action, typename Tuple>
static void call(Action &action, Tuple &tup)
{
action.template operator()<I>(tup);
using recursive = void_fold_tuple_<I+1, N>;
recursive::call(action, tup);
}
};
template <size_t N>
struct void_fold_tuple_<N, N> {
template <typename Action, typename Tuple>
static void call(Action&, Tuple&) { /* no-op */ }
};
struct print_action {
template <typename Tuple, size_t I>
void operator()(Tuple &tup) {
using std::get; // ADL
std::cout << std::get<I>(tup) << " ";
}
};
template <typename Action, typename Tuple>
void void_fold_tuple(Action &&action, Tuple &&tup)
{
using std::tuple_size; // ADL
using tuple = typename std::remove_reference<Tuple>::type;
using recursive = void_fold_tuple_<0, tuple_size<tuple>::value>;
recursive::call(action, tup);
}
int main() {
std::tuple<int, double, char const *> tup{1,3.14,"hi",std::endl};
void_fold_tuple(print_action{}, tup);
};
If something like the #N syntax were available then it would simplify back
to something that resembles strongly the first case:
template <typename Action, template <typename ...> class Tuple, typename
....FTs>
void void_fold_tuple(Action &&action, Tuple<FTs...> &&tup)
{
auto x = {void_fold_one(action, std::get<#FTs>(tup)...)};
(void) x;
}
int main() {
std::tuple<int, double, char const *> tup{1, 3.14, "hi", std::endl};
void_fold_tuple(print_action{}, tup);
};
Example 3
====================
Suppose we want to initialize the contents of a std::tuple using a
std::vector (this actually arose in our code when we have templated child
classes that specialize a virtual base class used elsewhere). Right now the
only way to achieve it is something like the following:
template<int...>
struct Sequence { };
template<size_t N, size_t... S>
struct GenSequence {
using type = typename GenSequence<N-1, N-1, S...>::type;
};
template<size_t... S>
struct GenSequence<0, S...>
{
using type = Sequence<S...>;
};
template <typename... Ts>
struct Foo {
using Tuple = std::tuple<Ts* ...>;
using Vector = std::vector<void*>;
using Seq = typename GenSequence<sizeof...(Ts)>::type;
Foo(Vector const &v) {
init_pointers(v, Seq());
}
template <size_t ... S>
void init_pointers(Vector const &v, Seq) {
_pointers = Tuple{dynamic_cast<Ts*>(v[S])...};
}
Tuple _pointers;
};
With the new syntax that would simplify to:
template <typename... Ts>
struct Foo {
using Tuple = std::tuple<Ts* ...>;
using Vector = std::vector<void*>;
Foo(Vector const &v)
: _pointers{dynamic_cast<Ts*>(v[#Ts])...}
{
}
Tuple _pointers;
};
Example 4
====================
Suppose I wanted to define a function that reverses the fields of a tuple.
With the proposed syntax it would not be difficult to write such a function:
template <size_t M, typename T, typename... Ts>
struct Select{
using type = typename Select<M - 1, Ts...>::type;
};
template <typename T, typename... Ts>
struct Select<0, T, Ts...>{
using type = T;
};
template <template <typename...> class Tuple, typename... Ts>
auto reverse(Tuple<Ts...> const &tup) {
static constexpr size_t const N = sizeof...(Ts) - 1;
using RTuple = Tuple<typename Select<N - #Ts, Ts...>::type...>;
return RTuple<{std::get<N-#Ts>(tup)...};
}
I'll leave the vanilla C++14 version of the above function as an exercise
for the reader...
Thoughts?
Ryan Johnson
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_5286_1522603086.1437415718862
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi,<br><br>Variadic template parameters are really nice, a=
nd it's really
impressive how complex of expressions you can unpack (with more coming=20
once C++17 allows folds). However, there is currently a glaring gap in=20
the feature: you can't access the position number of a type when=20
unpacking a parameter pack. This makes it unnecessarily hard to write=20
code that mixes parameter packs and tuples, because the one works with=20
variadic lists of types and the other requires use of=20
std::get<size_t>.<br><br>The idea I'd like to float, then, is tha=
t the position of a given type within its pack should be accessible during =
unpacking:<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 18=
7, 187); border-image: none; -ms-word-wrap: break-word; background-color: r=
gb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprin=
t"><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">temp=
late</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);=
"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, =
0);"><</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0=
, 136);">typename</span><span class=3D"styled-by-prettify" style=3D"color: =
rgb(102, 102, 0);">...</span><span class=3D"styled-by-prettify" style=3D"co=
lor: rgb(102, 0, 102);">Ts</span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(102, 102, 0);">></span><span class=3D"styled-by-prettify"=
style=3D"color: rgb(0, 0, 0);"><br>std</span><span class=3D"styled-by-pret=
tify" style=3D"color: rgb(102, 102, 0);">::</span><span class=3D"styled-by-=
prettify" style=3D"color: rgb(0, 0, 0);">vector</span><span class=3D"styled=
-by-prettify" style=3D"color: rgb(0, 136, 0);"><size_t></span><span c=
lass=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> foo</span><span=
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">(</span><s=
pan class=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);">Ts</spa=
n><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">&am=
p;&</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, =
0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 10=
2, 0);">...)</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0=
, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(10=
2, 102, 0);">{</span><span class=3D"styled-by-prettify" style=3D"color: rgb=
(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(=
0, 0, 136);">return</span><span class=3D"styled-by-prettify" style=3D"color=
: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color:=
rgb(102, 102, 0);">{</span><span class=3D"styled-by-prettify" style=3D"col=
or: rgb(136, 0, 0);">#Ts...}; }</span><span class=3D"styled-by-prettify" st=
yle=3D"color: rgb(0, 0, 0);"><br><br></span><span class=3D"styled-by-pretti=
fy" style=3D"color: rgb(0, 0, 136);">int</span><span class=3D"styled-by-pre=
ttify" style=3D"color: rgb(0, 0, 0);"> main</span><span class=3D"styled-by-=
prettify" style=3D"color: rgb(102, 102, 0);">()</span><span class=3D"styled=
-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-=
by-prettify" style=3D"color: rgb(102, 102, 0);">{</span><span class=3D"styl=
ed-by-prettify" style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0std</span><=
span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">::</sp=
an><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);">vector=
a</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0=
);">{</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 102, =
102);">0</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, =
102, 0);">,</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0,=
102, 102);">1</span><span class=3D"styled-by-prettify" style=3D"color: rgb=
(102, 102, 0);">,</span><span class=3D"styled-by-prettify" style=3D"color: =
rgb(0, 102, 102);">2</span><span class=3D"styled-by-prettify" style=3D"colo=
r: rgb(102, 102, 0);">},</span><span class=3D"styled-by-prettify" style=3D"=
color: rgb(0, 0, 0);"> b</span><span class=3D"styled-by-prettify" style=3D"=
color: rgb(102, 102, 0);">=3D</span><span class=3D"styled-by-prettify" styl=
e=3D"color: rgb(0, 0, 0);">foo</span><span class=3D"styled-by-prettify" sty=
le=3D"color: rgb(102, 102, 0);">(</span><span class=3D"styled-by-prettify" =
style=3D"color: rgb(0, 136, 0);">"hi"</span><span class=3D"styled=
-by-prettify" style=3D"color: rgb(102, 102, 0);">,</span><span class=3D"sty=
led-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styl=
ed-by-prettify" style=3D"color: rgb(0, 136, 0);">"ho"</span><span=
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">,</span><s=
pan class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span><sp=
an class=3D"styled-by-prettify" style=3D"color: rgb(0, 136, 0);">"hum&=
quot;</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
, 0);">);</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0=
, 0);"><br>=C2=A0 =C2=A0</span><span class=3D"styled-by-prettify" style=3D"=
color: rgb(0, 0, 136);">assert</span><span class=3D"styled-by-prettify" sty=
le=3D"color: rgb(102, 102, 0);">(</span><span class=3D"styled-by-prettify" =
style=3D"color: rgb(0, 0, 0);">a </span><span class=3D"styled-by-prettify" =
style=3D"color: rgb(102, 102, 0);">=3D=3D</span><span class=3D"styled-by-pr=
ettify" style=3D"color: rgb(0, 0, 0);"> b</span><span class=3D"styled-by-pr=
ettify" style=3D"color: rgb(102, 102, 0);">);</span><span class=3D"styled-b=
y-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by=
-prettify" style=3D"color: rgb(136, 0, 0);">// succeeds</span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br></span><span cla=
ss=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">}</span><span =
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br></span></di=
v></code></div><br>The
above function is clearly a toy example, and the exact syntax need not=20
be '#Ts' but hopefully it conveys the idea. The feature would compl=
ement
the existing sizeof...() operator, and I do not think it would be=20
difficult to provide compiler support for it (though I am by no means a=20
compiler expert).<br><br>The rest of this message consists of examples=20
to show why such a syntax might be useful. The first three examples were
extracted from real-life scenarios I encountered in my work, though=20
they have been simplified drastically here to be more concise. The last=20
example I made up, to show something that would be really unpleasant to=20
express without the proposed syntax.<br><br>Apologies in advance if this id=
ea has already been floated in the=20
past---a search of this forum did not turn up any obvious matches, but=20
that doesn't mean much.<br><br>Example 1: <br>=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br><br>Suppose
I have some code that assigns values to a std::tuple which are=20
constructible and assignable---but not convertible---to the tuple's=20
field types. This means I can't write this:<br><div class=3D"prettyprin=
t" style=3D"border: 1px solid rgb(187, 187, 187); border-image: none; -ms-w=
ord-wrap: break-word; background-color: rgb(250, 250, 250);"><code class=3D=
"prettyprint"><div class=3D"subprettyprint"><span class=3D"styled-by-pretti=
fy" style=3D"color: rgb(0, 0, 136);">template</span><span class=3D"styled-b=
y-prettify" style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by=
-prettify" style=3D"color: rgb(102, 102, 0);"><</span><span class=3D"sty=
led-by-prettify" style=3D"color: rgb(0, 0, 136);">typename</span><span clas=
s=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> T</span><span clas=
s=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">></span><spa=
n class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br></span><s=
pan class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">struct</s=
pan><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </sp=
an><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);">St=
oredType</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,=
0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 1=
02, 0);">{</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, =
0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0=
, 136);">using</span><span class=3D"styled-by-prettify" style=3D"color: rgb=
(0, 0, 0);"> type</span><span class=3D"styled-by-prettify" style=3D"color: =
rgb(102, 102, 0);">=3D</span><span class=3D"styled-by-prettify" style=3D"co=
lor: rgb(0, 0, 0);">T</span><span class=3D"styled-by-prettify" style=3D"col=
or: rgb(102, 102, 0);">;</span><span class=3D"styled-by-prettify" style=3D"=
color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"c=
olor: rgb(102, 102, 0);">};</span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(0, 0, 0);"><br></span><span class=3D"styled-by-prettify" sty=
le=3D"color: rgb(0, 0, 0);"><br></span><span class=3D"styled-by-prettify" s=
tyle=3D"color: rgb(136, 0, 0);">/* various specializations of StoredType fo=
llow, but <br>=C2=A0* </span><span class=3D"styled-by-prettify" style=3D"co=
lor: rgb(136, 0, 0);"><code class=3D"prettyprint"><span class=3D"styled-by-=
prettify" style=3D"color: rgb(136, 0, 0);"><code class=3D"prettyprint"><spa=
n class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);"><code class=
=3D"prettyprint"><span class=3D"styled-by-prettify" style=3D"color: rgb(136=
, 0, 0);">std::is_constructible<StoredType<T>::type, T> always =
holds</span></code></span></code></span></code><br>=C2=A0*/</span><span cla=
ss=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br></span><span c=
lass=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">template</span=
><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </span>=
<span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);"><<=
/span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">t=
ypename</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 1=
02, 0);">...</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0=
, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(10=
2, 0, 102);">FTs</span><span class=3D"styled-by-prettify" style=3D"color: r=
gb(102, 102, 0);">></span><span class=3D"styled-by-prettify" style=3D"co=
lor: rgb(0, 0, 0);"><br></span><span class=3D"styled-by-prettify" style=3D"=
color: rgb(0, 0, 136);">struct</span><span class=3D"styled-by-prettify" sty=
le=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" styl=
e=3D"color: rgb(102, 0, 102);">Foo</span><span class=3D"styled-by-prettify"=
style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" =
style=3D"color: rgb(102, 102, 0);">{</span><span class=3D"styled-by-prettif=
y" style=3D"color: rgb(0, 0, 0);"><br>=C2=A0=C2=A0 std::tuple<typename S=
toredType<FTs>::type...> _data;<br><br>=C2=A0 =C2=A0</span><span c=
lass=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);">Foo</span><s=
pan class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">(</span=
><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);">FTs<=
/span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> </=
span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">co=
nst</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0=
);">&</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0=
, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, =
102, 0);">...</span><span class=3D"styled-by-prettify" style=3D"color: rgb(=
0, 0, 0);">args</span><span class=3D"styled-by-prettify" style=3D"color: rg=
b(102, 102, 0);">)</span><span class=3D"styled-by-prettify" style=3D"color:=
rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: =
rgb(102, 102, 0);">:</span><span class=3D"styled-by-prettify" style=3D"colo=
r: rgb(0, 0, 0);"> _data{args...} { } // error!<br></span><span class=3D"st=
yled-by-prettify" style=3D"color: rgb(102, 102, 0);">};</span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br></span></div></c=
ode></div><br>Instead, the constructor needs a hack like the following:<br>=
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187, 187); b=
order-image: none; -ms-word-wrap: break-word; background-color: rgb(250, 25=
0, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span c=
lass=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);">Foo(FTs cons=
t & ...args) { init_data<0,FTs...>(args...); }</span><span class=
=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);"></span><br><br>t=
emplate <size_t M, typename T, typename... Rest><br>void init_data(T =
const &arg, Rest const & ...rest) {<br>=C2=A0=C2=A0 std::get<M&g=
t;(_data) =3D arg;<br>=C2=A0=C2=A0 init_data<M+1, Rest...>(rest...);<=
br>}<br><br>template <size_t M, typename T><br>void init_data(T const=
&arg) {<br>=C2=A0=C2=A0 std::get<M>(_data) =3D arg;<br>}<br></di=
v></code></div><br>If there were a way to access type positions in a parame=
ter pack, the constructor hack would be much simpler and cleaner:<br><div c=
lass=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187, 187); border-=
image: none; -ms-word-wrap: break-word; background-color: rgb(250, 250, 250=
);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span class=
=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);">Foo(FTs const &a=
mp; ...args) { <br>=C2=A0=C2=A0 auto x =3D {(std::get<#FTs>(_data)=3D=
args)...}; <br>=C2=A0=C2=A0 (void) x;<br>}<br></span></div></code></div><br=
>(I know that N4387 will address this particular problem, but that's b=
esides the point)<br><br>Example 2: <br>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D<br><br>Consider
a fold function that accepts some number of inputs and applies an=20
action to each of them (vaguely similar to what C++17 is likely to=20
support). If the values to be folded are provided as arguments to a=20
variadic template function, then it's really easy (assuming C++14=20
generic lambdas):<br><div class=3D"prettyprint" style=3D"border: 1px solid =
rgb(187, 187, 187); border-image: none; -ms-word-wrap: break-word; backgrou=
nd-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"su=
bprettyprint"><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 0=
, 102);"><code class=3D"prettyprint">// workaround for fact that we can'=
;t make a std::initializer_list<void><br>template <typename Action=
, typename T><br>bool void_fold_one(Action &action, T &&t) {=
<br>=C2=A0=C2=A0 action(std::forward<T>(t));<br>=C2=A0=C2=A0 return t=
rue;<br>}<br><br></code>template <typename Action, typename T, typename.=
... Ts><br>void void_fold(Action &&action, T &&t, Ts&=
&... args)<br>{<br>=C2=A0=C2=A0 auto x =3D {void_fold_one(action, std::=
forward<T>(t))...};<br>=C2=A0=C2=A0 (void) x;<br>}<br><br>int main() =
{<br>=C2=A0=C2=A0 auto action =3D [](auto x) { std::cout << x <<=
; " "; };<br>=C2=A0=C2=A0 void_fold(action, 1, 3.14, "hi&quo=
t;, std::endl);<br>}<br></span><span class=3D"styled-by-prettify" style=3D"=
color: rgb(102, 102, 0);"></span></div></code></div><code class=3D"prettypr=
int"></code><br><br>Now try to do that with a std::tuple instead and you en=
d up with something much less satisfying:<br><div class=3D"prettyprint" sty=
le=3D"border: 1px solid rgb(187, 187, 187); border-image: none; -ms-word-wr=
ap: break-word; background-color: rgb(250, 250, 250);"><code class=3D"prett=
yprint"><div class=3D"subprettyprint"><span class=3D"styled-by-prettify" st=
yle=3D"color: rgb(102, 0, 102);">template <size_t I, size_t N><br>str=
uct void_fold_tuple_ {<br>=C2=A0=C2=A0 template <typename Action, typena=
me Tuple><br>=C2=A0=C2=A0 static void call(Action &action, Tuple &am=
p;tup)<br>=C2=A0=C2=A0 {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 action.template =
operator()<I>(tup);<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 using recursive=
=3D void_fold_tuple_<I+1, N>;<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 recu=
rsive::call(action, tup);<br>=C2=A0=C2=A0 }<br>};<br><br>template <size_=
t N><br>struct void_fold_tuple_<N, N> {<br>=C2=A0=C2=A0 template &=
lt;typename Action, typename Tuple><br>=C2=A0=C2=A0 static void call(Act=
ion&, Tuple&) { /* no-op */ }<br>};<br><br>struct print_action {<br=
>=C2=A0=C2=A0 template <typename Tuple, size_t I><br>=C2=A0=C2=A0 voi=
d operator()(Tuple &tup) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 using std:=
:get; // ADL<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::cout << std::get&=
lt;I>(tup) << " ";<br>=C2=A0=C2=A0 }<br>};<br><br>templa=
te <typename Action, typename Tuple><br>void void_fold_tuple(Action &=
amp;&action, Tuple &&tup)<br>{<br>=C2=A0=C2=A0 using std::tuple=
_size; // ADL<br>=C2=A0=C2=A0 using tuple =3D typename std::remove_referenc=
e<Tuple>::type;<br>=C2=A0=C2=A0 using recursive =3D void_fold_tuple_&=
lt;0, tuple_size<tuple>::value>;<br>=C2=A0=C2=A0 recursive::call(a=
ction, tup);<br>}<br><br>int main() {<br>=C2=A0=C2=A0 std::tuple<int, do=
uble, char const *> tup{1,3.14,"hi",std::endl};<br></span><spa=
n class=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);"><code cla=
ss=3D"prettyprint"><code class=3D"prettyprint"><span class=3D"styled-by-pre=
ttify" style=3D"color: rgb(102, 0, 102);">=C2=A0=C2=A0 void_fold_tuple(prin=
t_action{}, tup);<br></span></code></code>};<br></span><span class=3D"style=
d-by-prettify" style=3D"color: rgb(102, 102, 0);"></span></div></code></div=
><br>If something like the #N syntax were available then it would simplify =
back to something that resembles strongly the first case:<br><div class=3D"=
prettyprint" style=3D"border: 1px solid rgb(187, 187, 187); border-image: n=
one; -ms-word-wrap: break-word; background-color: rgb(250, 250, 250);"><cod=
e class=3D"prettyprint"><div class=3D"subprettyprint"><span class=3D"styled=
-by-prettify" style=3D"color: rgb(102, 0, 102);"></span><code class=3D"pret=
typrint"><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102=
);">template <typename Action, template <typename ...> class Tuple=
, typename ...FTs><br>void void_fold_tuple(Action &&action, Tupl=
e<FTs...> &&tup)<br>{<br>=C2=A0=C2=A0 auto x =3D {void_fold_o=
ne(action, std::get<#FTs>(tup)...)};<br>=C2=A0=C2=A0 (void) x;<br>}<b=
r><br>int main() {<br>=C2=A0=C2=A0 std::tuple<int, double, char const *&=
gt; tup{1, 3.14, "hi", std::endl};<br>=C2=A0=C2=A0 void_fold_tupl=
e(print_action{}, tup);<br>};</span></code></div></code></div><br>Example 3=
<br>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br><br>Sup=
pose
we want to initialize the contents of a std::tuple using a std::vector=20
(this actually arose in our code when we have templated child classes=20
that specialize a virtual base class used elsewhere). Right now the only
way to achieve it is something like the following:<br><div class=3D"pretty=
print" style=3D"border: 1px solid rgb(187, 187, 187); border-image: none; -=
ms-word-wrap: break-word; background-color: rgb(250, 250, 250);"><code clas=
s=3D"prettyprint"><div class=3D"subprettyprint"><span class=3D"styled-by-pr=
ettify" style=3D"color: rgb(102, 0, 102);">template<int...><br>struct=
Sequence { };<br><br>template<size_t N, </span><span class=3D"styled-by=
-prettify" style=3D"color: rgb(102, 0, 102);"><code class=3D"prettyprint"><=
span class=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);">size_t=
</span></code>... S><br>struct GenSequence {<br>=C2=A0=C2=A0 using type =
=3D typename GenSequence<N-1, N-1, S...>::type;<br>};<br><br>template=
<</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 1=
02);"><code class=3D"prettyprint"><span class=3D"styled-by-prettify" style=
=3D"color: rgb(102, 0, 102);">size_t</span></code>... S><br>struct GenSe=
quence<0, S...><br>{<br>=C2=A0=C2=A0 using type =3D Sequence<S...&=
gt;;<br>};<br><br>template <typename... Ts><br>struct Foo {<br>=C2=A0=
=C2=A0 using Tuple =3D </span><span class=3D"styled-by-prettify" style=3D"c=
olor: rgb(102, 0, 102);"><code class=3D"prettyprint"><span class=3D"styled-=
by-prettify" style=3D"color: rgb(102, 0, 102);">std::tuple<Ts* ...>;<=
br>=C2=A0=C2=A0 using Vector =3D std::vector<void*>;<br></span></code=
> =C2=A0=C2=A0 using Seq =3D typename GenSequence<sizeof...(Ts)>::typ=
e;<br><br>=C2=A0=C2=A0 Foo(Vector const &v) {<br>=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0 init_pointers(v, Seq());<br>=C2=A0=C2=A0 }<br><br>=C2=A0=C2=A0 te=
mplate <size_t ... S><br>=C2=A0=C2=A0 void init_pointers(Vector const=
&v, Seq) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 _pointers =3D Tuple{dynam=
ic_cast<Ts*>(v[S])...};<br>=C2=A0=C2=A0 }<br><br>=C2=A0=C2=A0 Tuple _=
pointers;<br>};<br></span><span class=3D"styled-by-prettify" style=3D"color=
: rgb(102, 102, 0);"></span></div></code></div><br>With the new syntax that=
would simplify to:<br><div class=3D"prettyprint" style=3D"border: 1px soli=
d rgb(187, 187, 187); border-image: none; -ms-word-wrap: break-word; backgr=
ound-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"=
subprettyprint"><code class=3D"prettyprint"><span class=3D"styled-by-pretti=
fy" style=3D"color: rgb(102, 0, 102);">template <typename... Ts><br>s=
truct Foo {<br>=C2=A0=C2=A0 using Tuple =3D </span><span class=3D"styled-by=
-prettify" style=3D"color: rgb(102, 0, 102);"><code class=3D"prettyprint"><=
span class=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);">std::t=
uple<Ts* ...>;<br>=C2=A0=C2=A0 using Vector =3D std::vector<void*&=
gt;;<br></span></code><br>=C2=A0=C2=A0 Foo(Vector const &v) <br>=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 : _pointers{dynamic_cast<Ts*>(v[#Ts])...}<br=
>=C2=A0=C2=A0 {<br>=C2=A0=C2=A0 }<br><br>=C2=A0=C2=A0 Tuple _pointers;<br>}=
;<br></span></code><span class=3D"styled-by-prettify" style=3D"color: rgb(1=
02, 102, 0);"></span></div></code></div><br>Example 4<br>=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br><br>Suppose
I wanted to define a function that reverses the fields of a tuple. With
the proposed syntax it would not be difficult to write such a function:<br=
><div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187, 187); =
border-image: none; -ms-word-wrap: break-word; background-color: rgb(250, 2=
50, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span =
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);">template &l=
t;size_t M, typename T, typename... Ts><br>struct Select{<br>=C2=A0=C2=
=A0=C2=A0 using type =3D typename Select<M - 1, Ts...>::type;<br>};<b=
r><br>template <typename T, typename... Ts><br>struct Select<0, T,=
Ts...>{<br>=C2=A0=C2=A0=C2=A0 using type =3D T;<br>};<br><br>template &=
lt;template <typename...> class Tuple, typename... Ts><br>auto rev=
erse(Tuple<Ts...> const &tup) {<br>=C2=A0=C2=A0 static constexpr =
size_t const N =3D </span><span class=3D"styled-by-prettify" style=3D"color=
: rgb(102, 0, 102);"><code class=3D"prettyprint"><span class=3D"styled-by-p=
rettify" style=3D"color: rgb(102, 0, 102);"><code class=3D"prettyprint"><sp=
an class=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);">sizeof..=
..(Ts) - 1;</span></code></span></code><br>=C2=A0=C2=A0 using RTuple =3D </s=
pan><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 0, 102);"><=
code class=3D"prettyprint"><span class=3D"styled-by-prettify" style=3D"colo=
r: rgb(102, 0, 102);">Tuple<typename Select<N - #Ts, Ts...>::type.=
...>;<br>=C2=A0</span></code>=C2=A0 return RTuple<{std::get<N-#Ts&g=
t;(tup)...};<br>}<br></span><span class=3D"styled-by-prettify" style=3D"col=
or: rgb(102, 102, 0);"></span></div></code></div><br>I'll leave the van=
illa C++14 version of the above function as an exercise for the reader...<b=
r><br>Thoughts?<br>Ryan Johnson</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_5286_1522603086.1437415718862--
------=_Part_5285_2072225703.1437415718860--
.
Author: Edward Catmur <ed@catmur.co.uk>
Date: Mon, 20 Jul 2015 15:54:08 -0700 (PDT)
Raw View
------=_Part_4774_2007236009.1437432848916
Content-Type: multipart/alternative;
boundary="----=_Part_4775_1054090686.1437432848917"
------=_Part_4775_1054090686.1437432848917
Content-Type: text/plain; charset=UTF-8
I think n3728 or something similar would provide what you're after, with
reasonable syntax. If typelists become enough of a first-class citizen that
it becomes possible to introduce a typelist into scope and then expand it
with natural syntax, then it becomes plausible that you could write:
template <typename...Ts>
std::vector<size_t> foo(Ts&& ...) { return {std::index_sequence_for<Ts...>::
value...}; }
Here, std::integer_sequence has been augmented with a typelist holding its
compile-time integer sequence:
template<class T, T... Ints>
struct integer_sequence {
using value_type = T;
using value = <Ints...>; // new typelist member after n3728; syntax
TBD
static constexpr std::size_t size() { return sizeof...(Ints); }
};
Does anyone know what kind of reception Mike got at Chicago when presenting
n3728?
On Monday, 20 July 2015 19:08:39 UTC+1, sco...@gmail.com wrote:
>
> Hi,
>
> Variadic template parameters are really nice, and it's really impressive
> how complex of expressions you can unpack (with more coming once C++17
> allows folds). However, there is currently a glaring gap in the feature:
> you can't access the position number of a type when unpacking a parameter
> pack. This makes it unnecessarily hard to write code that mixes parameter
> packs and tuples, because the one works with variadic lists of types and
> the other requires use of std::get<size_t>.
>
> The idea I'd like to float, then, is that the position of a given type
> within its pack should be accessible during unpacking:
> template <typename...Ts>
> std::vector<size_t> foo(Ts&& ...) { return {#Ts...}; }
>
> int main() {
> std::vector a{0,1,2}, b=foo("hi", "ho", "hum");
> assert(a == b); // succeeds
> }
>
> The above function is clearly a toy example, and the exact syntax need not
> be '#Ts' but hopefully it conveys the idea. The feature would complement
> the existing sizeof...() operator, and I do not think it would be difficult
> to provide compiler support for it (though I am by no means a compiler
> expert).
>
> The rest of this message consists of examples to show why such a syntax
> might be useful. The first three examples were extracted from real-life
> scenarios I encountered in my work, though they have been simplified
> drastically here to be more concise. The last example I made up, to show
> something that would be really unpleasant to express without the proposed
> syntax.
>
> Apologies in advance if this idea has already been floated in the past---a
> search of this forum did not turn up any obvious matches, but that doesn't
> mean much.
>
> Example 1:
> ====================
>
> Suppose I have some code that assigns values to a std::tuple which are
> constructible and assignable---but not convertible---to the tuple's field
> types. This means I can't write this:
> template <typename T>
> struct StoredType { using type=T; };
>
> /* various specializations of StoredType follow, but
> * std::is_constructible<StoredType<T>::type, T> always holds
> */
> template <typename... FTs>
> struct Foo {
> std::tuple<typename StoredType<FTs>::type...> _data;
>
> Foo(FTs const & ...args) : _data{args...} { } // error!
> };
>
> Instead, the constructor needs a hack like the following:
> Foo(FTs const & ...args) { init_data<0,FTs...>(args...); }
>
> template <size_t M, typename T, typename... Rest>
> void init_data(T const &arg, Rest const & ...rest) {
> std::get<M>(_data) = arg;
> init_data<M+1, Rest...>(rest...);
> }
>
> template <size_t M, typename T>
> void init_data(T const &arg) {
> std::get<M>(_data) = arg;
> }
>
> If there were a way to access type positions in a parameter pack, the
> constructor hack would be much simpler and cleaner:
> Foo(FTs const & ...args) {
> auto x = {(std::get<#FTs>(_data)=args)...};
> (void) x;
> }
>
> (I know that N4387 will address this particular problem, but that's
> besides the point)
>
> Example 2:
> ====================
>
> Consider a fold function that accepts some number of inputs and applies an
> action to each of them (vaguely similar to what C++17 is likely to
> support). If the values to be folded are provided as arguments to a
> variadic template function, then it's really easy (assuming C++14 generic
> lambdas):
> // workaround for fact that we can't make a std::initializer_list<void>
> template <typename Action, typename T>
> bool void_fold_one(Action &action, T &&t) {
> action(std::forward<T>(t));
> return true;
> }
>
> template <typename Action, typename T, typename... Ts>
> void void_fold(Action &&action, T &&t, Ts&&... args)
> {
> auto x = {void_fold_one(action, std::forward<T>(t))...};
> (void) x;
> }
>
> int main() {
> auto action = [](auto x) { std::cout << x << " "; };
> void_fold(action, 1, 3.14, "hi", std::endl);
> }
>
>
> Now try to do that with a std::tuple instead and you end up with something
> much less satisfying:
> template <size_t I, size_t N>
> struct void_fold_tuple_ {
> template <typename Action, typename Tuple>
> static void call(Action &action, Tuple &tup)
> {
> action.template operator()<I>(tup);
> using recursive = void_fold_tuple_<I+1, N>;
> recursive::call(action, tup);
> }
> };
>
> template <size_t N>
> struct void_fold_tuple_<N, N> {
> template <typename Action, typename Tuple>
> static void call(Action&, Tuple&) { /* no-op */ }
> };
>
> struct print_action {
> template <typename Tuple, size_t I>
> void operator()(Tuple &tup) {
> using std::get; // ADL
> std::cout << std::get<I>(tup) << " ";
> }
> };
>
> template <typename Action, typename Tuple>
> void void_fold_tuple(Action &&action, Tuple &&tup)
> {
> using std::tuple_size; // ADL
> using tuple = typename std::remove_reference<Tuple>::type;
> using recursive = void_fold_tuple_<0, tuple_size<tuple>::value>;
> recursive::call(action, tup);
> }
>
> int main() {
> std::tuple<int, double, char const *> tup{1,3.14,"hi",std::endl};
> void_fold_tuple(print_action{}, tup);
> };
>
> If something like the #N syntax were available then it would simplify back
> to something that resembles strongly the first case:
> template <typename Action, template <typename ...> class Tuple, typename
> ...FTs>
> void void_fold_tuple(Action &&action, Tuple<FTs...> &&tup)
> {
> auto x = {void_fold_one(action, std::get<#FTs>(tup)...)};
> (void) x;
> }
>
> int main() {
> std::tuple<int, double, char const *> tup{1, 3.14, "hi", std::endl};
> void_fold_tuple(print_action{}, tup);
> };
>
> Example 3
> ====================
>
> Suppose we want to initialize the contents of a std::tuple using a
> std::vector (this actually arose in our code when we have templated child
> classes that specialize a virtual base class used elsewhere). Right now the
> only way to achieve it is something like the following:
> template<int...>
> struct Sequence { };
>
> template<size_t N, size_t... S>
> struct GenSequence {
> using type = typename GenSequence<N-1, N-1, S...>::type;
> };
>
> template<size_t... S>
> struct GenSequence<0, S...>
> {
> using type = Sequence<S...>;
> };
>
> template <typename... Ts>
> struct Foo {
> using Tuple = std::tuple<Ts* ...>;
> using Vector = std::vector<void*>;
> using Seq = typename GenSequence<sizeof...(Ts)>::type;
>
> Foo(Vector const &v) {
> init_pointers(v, Seq());
> }
>
> template <size_t ... S>
> void init_pointers(Vector const &v, Seq) {
> _pointers = Tuple{dynamic_cast<Ts*>(v[S])...};
> }
>
> Tuple _pointers;
> };
>
> With the new syntax that would simplify to:
> template <typename... Ts>
> struct Foo {
> using Tuple = std::tuple<Ts* ...>;
> using Vector = std::vector<void*>;
>
> Foo(Vector const &v)
> : _pointers{dynamic_cast<Ts*>(v[#Ts])...}
> {
> }
>
> Tuple _pointers;
> };
>
> Example 4
> ====================
>
> Suppose I wanted to define a function that reverses the fields of a tuple.
> With the proposed syntax it would not be difficult to write such a function:
> template <size_t M, typename T, typename... Ts>
> struct Select{
> using type = typename Select<M - 1, Ts...>::type;
> };
>
> template <typename T, typename... Ts>
> struct Select<0, T, Ts...>{
> using type = T;
> };
>
> template <template <typename...> class Tuple, typename... Ts>
> auto reverse(Tuple<Ts...> const &tup) {
> static constexpr size_t const N = sizeof...(Ts) - 1;
> using RTuple = Tuple<typename Select<N - #Ts, Ts...>::type...>;
> return RTuple<{std::get<N-#Ts>(tup)...};
> }
>
> I'll leave the vanilla C++14 version of the above function as an exercise
> for the reader...
>
> Thoughts?
> Ryan Johnson
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_4775_1054090686.1437432848917
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I think n3728 or something similar would provide what you&=
#39;re after, with reasonable syntax. If typelists become enough of a first=
-class citizen that it becomes possible to introduce a typelist into scope =
and then expand it with natural syntax, then it becomes plausible that you =
could write:<div><br></div><div><div class=3D"prettyprint" style=3D"border:=
1px solid rgb(187, 187, 187); word-wrap: break-word; background-color: rgb=
(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subprettyprint"=
><span style=3D"color: #008;" class=3D"styled-by-prettify">template</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"c=
olor: #008;" class=3D"styled-by-prettify">typename</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">...</span><span style=3D"color: #60=
6;" class=3D"styled-by-prettify">Ts</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">></span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br>std</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify">vector</span><span style=3D"color: #080;" class=3D"styled-by-pretti=
fy"><size_t></span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> foo</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">(</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Ts</spa=
n><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: #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"=
styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">st=
d</span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">index_sequence_fo=
r</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</spa=
n><span style=3D"color: #606;" class=3D"styled-by-prettify">Ts</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">...>::</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">value</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">...};</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"><br></span></div></code></div><div><br></div><div>H=
ere, <font face=3D"courier new, monospace">std::integer_sequence</font> has=
been augmented with a typelist holding its compile-time integer sequence:<=
/div><div><br></div><div class=3D"prettyprint" style=3D"border: 1px solid r=
gb(187, 187, 187); word-wrap: break-word; background-color: rgb(250, 250, 2=
50);"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #008;" class=3D"styled-by-prettify">template</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #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;" c=
lass=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> T</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">...</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Ints<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">></span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><font =
color=3D"#000088"><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>struct</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span></font><span style=3D"color: #000;" class=3D"styled-by-prettify">integ=
er_sequence</span><font color=3D"#666600"><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: #000;" class=3D"styled-by-pre=
ttify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">using</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> value_type </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">=3D</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><=
/font><span style=3D"color: #000;" class=3D"styled-by-prettify">=C2=A0 =C2=
=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">using<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> value </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</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"co=
lor: #606;" class=3D"styled-by-prettify">Ints</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">...>;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> =C2=A0 =C2=A0</span><span style=3D"color:=
#800;" class=3D"styled-by-prettify">// new typelist member after n3728; sy=
ntax TBD</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r></span><font color=3D"#666600"><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">static</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pre=
ttify">constexpr</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> 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 s=
ize</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: #660;" class=3D"styled-by-prettify">{</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">return</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">sizeof</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">...(</span><span style=3D"color: #606;" class=3D"styled-by-=
prettify">Ints</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></font><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">};</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code></di=
v><div><br></div><div>Does anyone know what kind of reception Mike got at C=
hicago when presenting n3728?=C2=A0<br><br>On Monday, 20 July 2015 19:08:39=
UTC+1, sco...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"=
margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;=
"><div dir=3D"ltr">Hi,<br><br>Variadic template parameters are really nice,=
and it's really
impressive how complex of expressions you can unpack (with more coming=20
once C++17 allows folds). However, there is currently a glaring gap in=20
the feature: you can't access the position number of a type when=20
unpacking a parameter pack. This makes it unnecessarily hard to write=20
code that mixes parameter packs and tuples, because the one works with=20
variadic lists of types and the other requires use of=20
std::get<size_t>.<br><br>The idea I'd like to float, then, is tha=
t the position of a given type within its pack should be accessible during =
unpacking:<div style=3D"border:1px solid rgb(187,187,187);background-color:=
rgb(250,250,250)"><code><div><span style=3D"color:rgb(0,0,136)">template</s=
pan><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,1=
02,0)"><</span><span style=3D"color:rgb(0,0,136)">typename</span><span s=
tyle=3D"color:rgb(102,102,0)">...</span><span style=3D"color:rgb(102,0,102)=
">Ts</span><span style=3D"color:rgb(102,102,0)">></span><span style=3D"c=
olor:rgb(0,0,0)"><br>std</span><span style=3D"color:rgb(102,102,0)">::</spa=
n><span style=3D"color:rgb(0,0,0)">vector</span><span style=3D"color:rgb(0,=
136,0)"><size_t></span><span style=3D"color:rgb(0,0,0)"> foo</span><s=
pan style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(102,0,1=
02)">Ts</span><span style=3D"color:rgb(102,102,0)">&&</span><span s=
tyle=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">...)=
</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(10=
2,102,0)">{</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"c=
olor:rgb(0,0,136)">return</span><span style=3D"color:rgb(0,0,0)"> </span><s=
pan style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(136,0,0=
)">#Ts...}; }</span><span style=3D"color:rgb(0,0,0)"><br><br></span><span s=
tyle=3D"color:rgb(0,0,136)">int</span><span style=3D"color:rgb(0,0,0)"> mai=
n</span><span style=3D"color:rgb(102,102,0)">()</span><span style=3D"color:=
rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">{</span><span styl=
e=3D"color:rgb(0,0,0)"><br>=C2=A0 =C2=A0std</span><span style=3D"color:rgb(=
102,102,0)">::</span><span style=3D"color:rgb(0,0,0)">vector a</span><span =
style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,102,102)"=
>0</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"color:=
rgb(0,102,102)">1</span><span style=3D"color:rgb(102,102,0)">,</span><span =
style=3D"color:rgb(0,102,102)">2</span><span style=3D"color:rgb(102,102,0)"=
>},</span><span style=3D"color:rgb(0,0,0)"> b</span><span style=3D"color:rg=
b(102,102,0)">=3D</span><span style=3D"color:rgb(0,0,0)">foo</span><span st=
yle=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(0,136,0)">&qu=
ot;hi"</span><span style=3D"color:rgb(102,102,0)">,</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,136,0)">"ho&q=
uot;</span><span style=3D"color:rgb(102,102,0)">,</span><span style=3D"colo=
r:rgb(0,0,0)"> </span><span style=3D"color:rgb(0,136,0)">"hum"</s=
pan><span style=3D"color:rgb(102,102,0)">);</span><span style=3D"color:rgb(=
0,0,0)"><br>=C2=A0 =C2=A0</span><span style=3D"color:rgb(0,0,136)">assert</=
span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb(=
0,0,0)">a </span><span style=3D"color:rgb(102,102,0)">=3D=3D</span><span st=
yle=3D"color:rgb(0,0,0)"> b</span><span style=3D"color:rgb(102,102,0)">);</=
span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(136,=
0,0)">// succeeds</span><span style=3D"color:rgb(0,0,0)"><br></span><span s=
tyle=3D"color:rgb(102,102,0)">}</span><span style=3D"color:rgb(0,0,0)"><br>=
</span></div></code></div><br>The
above function is clearly a toy example, and the exact syntax need not=20
be '#Ts' but hopefully it conveys the idea. The feature would compl=
ement
the existing sizeof...() operator, and I do not think it would be=20
difficult to provide compiler support for it (though I am by no means a=20
compiler expert).<br><br>The rest of this message consists of examples=20
to show why such a syntax might be useful. The first three examples were
extracted from real-life scenarios I encountered in my work, though=20
they have been simplified drastically here to be more concise. The last=20
example I made up, to show something that would be really unpleasant to=20
express without the proposed syntax.<br><br>Apologies in advance if this id=
ea has already been floated in the=20
past---a search of this forum did not turn up any obvious matches, but=20
that doesn't mean much.<br><br>Example 1: <br>=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br><br>Suppose
I have some code that assigns values to a std::tuple which are=20
constructible and assignable---but not convertible---to the tuple's=20
field types. This means I can't write this:<br><div style=3D"border:1px=
solid rgb(187,187,187);background-color:rgb(250,250,250)"><code><div><span=
style=3D"color:rgb(0,0,136)">template</span><span style=3D"color:rgb(0,0,0=
)"> </span><span style=3D"color:rgb(102,102,0)"><</span><span style=3D"c=
olor:rgb(0,0,136)">typename</span><span style=3D"color:rgb(0,0,0)"> T</span=
><span style=3D"color:rgb(102,102,0)">></span><span style=3D"color:rgb(0=
,0,0)"><br></span><span style=3D"color:rgb(0,0,136)">struct</span><span sty=
le=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,0,102)">Stored=
Type</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rg=
b(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,0,136)">using</span><span style=3D"color:rgb(0,0,0)"> type<=
/span><span style=3D"color:rgb(102,102,0)">=3D</span><span style=3D"color:r=
gb(0,0,0)">T</span><span style=3D"color:rgb(102,102,0)">;</span><span style=
=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">};</span=
><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,0=
)"><br></span><span style=3D"color:rgb(136,0,0)">/* various specializations=
of StoredType follow, but <br>=C2=A0* </span><span style=3D"color:rgb(136,=
0,0)"><code><span style=3D"color:rgb(136,0,0)"><code><span style=3D"color:r=
gb(0,0,136)"><code><span style=3D"color:rgb(136,0,0)">std::is_constructible=
<StoredType<T>::type, T> always holds</span></code></span></cod=
e></span></code><br>=C2=A0*/</span><span style=3D"color:rgb(0,0,0)"><br></s=
pan><span style=3D"color:rgb(0,0,136)">template</span><span style=3D"color:=
rgb(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)"><</span><span s=
tyle=3D"color:rgb(0,0,136)">typename</span><span style=3D"color:rgb(102,102=
,0)">...</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"colo=
r:rgb(102,0,102)">FTs</span><span style=3D"color:rgb(102,102,0)">></span=
><span style=3D"color:rgb(0,0,0)"><br></span><span style=3D"color:rgb(0,0,1=
36)">struct</span><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"c=
olor:rgb(102,0,102)">Foo</span><span style=3D"color:rgb(0,0,0)"> </span><sp=
an style=3D"color:rgb(102,102,0)">{</span><span style=3D"color:rgb(0,0,0)">=
<br>=C2=A0=C2=A0 std::tuple<typename StoredType<FTs>::type...> =
_data;<br><br>=C2=A0 =C2=A0</span><span style=3D"color:rgb(102,0,102)">Foo<=
/span><span style=3D"color:rgb(102,102,0)">(</span><span style=3D"color:rgb=
(102,0,102)">FTs</span><span style=3D"color:rgb(0,0,0)"> </span><span style=
=3D"color:rgb(0,0,136)">const</span><span style=3D"color:rgb(0,0,0)"> </spa=
n><span style=3D"color:rgb(102,102,0)">&</span><span style=3D"color:rgb=
(0,0,0)"> </span><span style=3D"color:rgb(102,102,0)">...</span><span style=
=3D"color:rgb(0,0,0)">args</span><span style=3D"color:rgb(102,102,0)">)</sp=
an><span style=3D"color:rgb(0,0,0)"> </span><span style=3D"color:rgb(102,10=
2,0)">:</span><span style=3D"color:rgb(0,0,0)"> _data{args...} { } // error=
!<br></span><span style=3D"color:rgb(102,102,0)">};</span><span style=3D"co=
lor:rgb(0,0,0)"><br></span></div></code></div><br>Instead, the constructor =
needs a hack like the following:<br><div style=3D"border:1px solid rgb(187,=
187,187);background-color:rgb(250,250,250)"><code><div><span style=3D"color=
:rgb(102,0,102)">Foo(FTs const & ...args) { init_data<0,FTs...>(a=
rgs...); }</span><span style=3D"color:rgb(102,102,0)"></span><br><br>templa=
te <size_t M, typename T, typename... Rest><br>void init_data(T const=
&arg, Rest const & ...rest) {<br>=C2=A0=C2=A0 std::get<M>(_d=
ata) =3D arg;<br>=C2=A0=C2=A0 init_data<M+1, Rest...>(rest...);<br>}<=
br><br>template <size_t M, typename T><br>void init_data(T const &=
;arg) {<br>=C2=A0=C2=A0 std::get<M>(_data) =3D arg;<br>}<br></div></c=
ode></div><br>If there were a way to access type positions in a parameter p=
ack, the constructor hack would be much simpler and cleaner:<br><div style=
=3D"border:1px solid rgb(187,187,187);background-color:rgb(250,250,250)"><c=
ode><div><span style=3D"color:rgb(102,0,102)">Foo(FTs const & ...args) =
{ <br>=C2=A0=C2=A0 auto x =3D {(std::get<#FTs>(_data)=3Dargs)...}; <b=
r>=C2=A0=C2=A0 (void) x;<br>}<br></span></div></code></div><br>(I know that=
N4387 will address this particular problem, but that's besides the po=
int)<br><br>Example 2: <br>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D<br><br>Consider
a fold function that accepts some number of inputs and applies an=20
action to each of them (vaguely similar to what C++17 is likely to=20
support). If the values to be folded are provided as arguments to a=20
variadic template function, then it's really easy (assuming C++14=20
generic lambdas):<br><div style=3D"border:1px solid rgb(187,187,187);backgr=
ound-color:rgb(250,250,250)"><code><div><span style=3D"color:rgb(102,0,102)=
"><code>// workaround for fact that we can't make a std::initializer_li=
st<void><br>template <typename Action, typename T><br>bool void=
_fold_one(Action &action, T &&t) {<br>=C2=A0=C2=A0 action(std::=
forward<T>(t));<br>=C2=A0=C2=A0 return true;<br>}<br><br></code>templ=
ate <typename Action, typename T, typename... Ts><br>void void_fold(A=
ction &&action, T &&t, Ts&&... args)<br>{<br>=C2=A0=
=C2=A0 auto x =3D {void_fold_one(action, std::forward<T>(t))...};<br>=
=C2=A0=C2=A0 (void) x;<br>}<br><br>int main() {<br>=C2=A0=C2=A0 auto action=
=3D [](auto x) { std::cout << x << " "; };<br>=C2=A0=
=C2=A0 void_fold(action, 1, 3.14, "hi", std::endl);<br>}<br></spa=
n><span style=3D"color:rgb(102,102,0)"></span></div></code></div><code></co=
de><br><br>Now try to do that with a std::tuple instead and you end up with=
something much less satisfying:<br><div style=3D"border:1px solid rgb(187,=
187,187);background-color:rgb(250,250,250)"><code><div><span style=3D"color=
:rgb(102,0,102)">template <size_t I, size_t N><br>struct void_fold_tu=
ple_ {<br>=C2=A0=C2=A0 template <typename Action, typename Tuple><br>=
=C2=A0=C2=A0 static void call(Action &action, Tuple &tup)<br>=C2=A0=
=C2=A0 {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 action.template operator()<I&=
gt;(tup);<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 using recursive =3D void_fold_t=
uple_<I+1, N>;<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 recursive::call(acti=
on, tup);<br>=C2=A0=C2=A0 }<br>};<br><br>template <size_t N><br>struc=
t void_fold_tuple_<N, N> {<br>=C2=A0=C2=A0 template <typename Acti=
on, typename Tuple><br>=C2=A0=C2=A0 static void call(Action&, Tuple&=
amp;) { /* no-op */ }<br>};<br><br>struct print_action {<br>=C2=A0=C2=A0 te=
mplate <typename Tuple, size_t I><br>=C2=A0=C2=A0 void operator()(Tup=
le &tup) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 using std::get; // ADL<br>=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::cout << std::get<I>(tup) &l=
t;< " ";<br>=C2=A0=C2=A0 }<br>};<br><br>template <typename =
Action, typename Tuple><br>void void_fold_tuple(Action &&action,=
Tuple &&tup)<br>{<br>=C2=A0=C2=A0 using std::tuple_size; // ADL<br=
>=C2=A0=C2=A0 using tuple =3D typename std::remove_reference<Tuple>::=
type;<br>=C2=A0=C2=A0 using recursive =3D void_fold_tuple_<0, tuple_size=
<tuple>::value>;<br>=C2=A0=C2=A0 recursive::call(action, tup);<br>=
}<br><br>int main() {<br>=C2=A0=C2=A0 std::tuple<int, double, char const=
*> tup{1,3.14,"hi",std::endl};<br></span><span style=3D"color=
:rgb(102,0,102)"><code><code><span style=3D"color:rgb(102,0,102)">=C2=A0=C2=
=A0 void_fold_tuple(print_action{}, tup);<br></span></code></code>};<br></s=
pan><span style=3D"color:rgb(102,102,0)"></span></div></code></div><br>If s=
omething like the #N syntax were available then it would simplify back to s=
omething that resembles strongly the first case:<br><div style=3D"border:1p=
x solid rgb(187,187,187);background-color:rgb(250,250,250)"><code><div><spa=
n style=3D"color:rgb(102,0,102)"></span><code><span style=3D"color:rgb(102,=
0,102)">template <typename Action, template <typename ...> class T=
uple, typename ...FTs><br>void void_fold_tuple(Action &&action, =
Tuple<FTs...> &&tup)<br>{<br>=C2=A0=C2=A0 auto x =3D {void_fo=
ld_one(action, std::get<#FTs>(tup)...)};<br>=C2=A0=C2=A0 (void) x;<br=
>}<br><br>int main() {<br>=C2=A0=C2=A0 std::tuple<int, double, char cons=
t *> tup{1, 3.14, "hi", std::endl};<br>=C2=A0=C2=A0 void_fold_=
tuple(print_action{}, tup);<br>};</span></code></div></code></div><br>Examp=
le 3<br>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br><br=
>Suppose
we want to initialize the contents of a std::tuple using a std::vector=20
(this actually arose in our code when we have templated child classes=20
that specialize a virtual base class used elsewhere). Right now the only
way to achieve it is something like the following:<br><div style=3D"border=
:1px solid rgb(187,187,187);background-color:rgb(250,250,250)"><code><div><=
span style=3D"color:rgb(102,0,102)">template<int...><br>struct Sequen=
ce { };<br><br>template<size_t N, </span><span style=3D"color:rgb(102,0,=
102)"><code><span style=3D"color:rgb(102,0,102)">size_t</span></code>... S&=
gt;<br>struct GenSequence {<br>=C2=A0=C2=A0 using type =3D typename GenSequ=
ence<N-1, N-1, S...>::type;<br>};<br><br>template<</span><span sty=
le=3D"color:rgb(102,0,102)"><code><span style=3D"color:rgb(102,0,102)">size=
_t</span></code>... S><br>struct GenSequence<0, S...><br>{<br>=C2=
=A0=C2=A0 using type =3D Sequence<S...>;<br>};<br><br>template <ty=
pename... Ts><br>struct Foo {<br>=C2=A0=C2=A0 using Tuple =3D </span><sp=
an style=3D"color:rgb(102,0,102)"><code><span style=3D"color:rgb(102,0,102)=
">std::tuple<Ts* ...>;<br>=C2=A0=C2=A0 using Vector =3D std::vector&l=
t;void*>;<br></span></code> =C2=A0=C2=A0 using Seq =3D typename GenSeque=
nce<sizeof...(Ts)>::type;<br><br>=C2=A0=C2=A0 Foo(Vector const &v=
) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 init_pointers(v, Seq());<br>=C2=A0=C2=
=A0 }<br><br>=C2=A0=C2=A0 template <size_t ... S><br>=C2=A0=C2=A0 voi=
d init_pointers(Vector const &v, Seq) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 _pointers =3D Tuple{dynamic_cast<Ts*>(v[S])...};<br>=C2=A0=C2=A0 =
}<br><br>=C2=A0=C2=A0 Tuple _pointers;<br>};<br></span><span style=3D"color=
:rgb(102,102,0)"></span></div></code></div><br>With the new syntax that wou=
ld simplify to:<br><div style=3D"border:1px solid rgb(187,187,187);backgrou=
nd-color:rgb(250,250,250)"><code><div><code><span style=3D"color:rgb(102,0,=
102)">template <typename... Ts><br>struct Foo {<br>=C2=A0=C2=A0 using=
Tuple =3D </span><span style=3D"color:rgb(102,0,102)"><code><span style=3D=
"color:rgb(102,0,102)">std::tuple<Ts* ...>;<br>=C2=A0=C2=A0 using Vec=
tor =3D std::vector<void*>;<br></span></code><br>=C2=A0=C2=A0 Foo(Vec=
tor const &v) <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 : _pointers{dynamic_ca=
st<Ts*>(v[#Ts])...}<br>=C2=A0=C2=A0 {<br>=C2=A0=C2=A0 }<br><br>=C2=A0=
=C2=A0 Tuple _pointers;<br>};<br></span></code><span style=3D"color:rgb(102=
,102,0)"></span></div></code></div><br>Example 4<br>=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br><br>Suppose
I wanted to define a function that reverses the fields of a tuple. With
the proposed syntax it would not be difficult to write such a function:<br=
><div style=3D"border:1px solid rgb(187,187,187);background-color:rgb(250,2=
50,250)"><code><div><span style=3D"color:rgb(102,0,102)">template <size_=
t M, typename T, typename... Ts><br>struct Select{<br>=C2=A0=C2=A0=C2=A0=
using type =3D typename Select<M - 1, Ts...>::type;<br>};<br><br>tem=
plate <typename T, typename... Ts><br>struct Select<0, T, Ts...>=
;{<br>=C2=A0=C2=A0=C2=A0 using type =3D T;<br>};<br><br>template <templa=
te <typename...> class Tuple, typename... Ts><br>auto reverse(Tupl=
e<Ts...> const &tup) {<br>=C2=A0=C2=A0 static constexpr size_t co=
nst N =3D </span><span style=3D"color:rgb(102,0,102)"><code><span style=3D"=
color:rgb(102,0,102)"><code><span style=3D"color:rgb(102,0,102)">sizeof...(=
Ts) - 1;</span></code></span></code><br>=C2=A0=C2=A0 using RTuple =3D </spa=
n><span style=3D"color:rgb(102,0,102)"><code><span style=3D"color:rgb(102,0=
,102)">Tuple<typename Select<N - #Ts, Ts...>::type...>;<br>=C2=
=A0</span></code>=C2=A0 return RTuple<{std::get<N-#Ts>(tup)...};<b=
r>}<br></span><span style=3D"color:rgb(102,102,0)"></span></div></code></di=
v><br>I'll leave the vanilla C++14 version of the above function as an =
exercise for the reader...<br><br>Thoughts?<br>Ryan Johnson</div></blockquo=
te></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_4775_1054090686.1437432848917--
------=_Part_4774_2007236009.1437432848916--
.
Author: scovich@gmail.com
Date: Mon, 20 Jul 2015 16:36:26 -0700 (PDT)
Raw View
------=_Part_2364_1422965832.1437435386983
Content-Type: multipart/alternative;
boundary="----=_Part_2365_384705389.1437435386984"
------=_Part_2365_384705389.1437435386984
Content-Type: text/plain; charset=UTF-8
Hmm. That's a very interesting proposal I didn't know about (thanks for the
heads-up!), but I'm not sure it actually solves the awkwardness I was
pointing out here: even if you had proper typelists, you'd still need some
(presumably recursive) variadic template helper(s) to convert a `template
<typename... Ts>' into a `template <size_t... Is>' for cases where you need
to index types. To implement this std::index_sequence_for that you mention,
for example, my proposed syntax would lead to something like:
template <typename... Ts>
struct index_sequence_for {
using value = <#Ts...>;
};
.... which is rather simpler than the alternatives I could imagine.
Also, my proposed syntax would make such a class largely unnecessary
because anyone wanting to turn a typelist into an integer sequence could
just use the same technique directly.
Still, if the other proposal brought as a side effect the ability to turn
type lists into integer sequences with less hoop-jumping than the current
status quo, I'd not complain too loudly.
On Monday, July 20, 2015 at 4:54:09 PM UTC-6, Edward Catmur wrote:
> I think n3728 or something similar would provide what you're after, with
> reasonable syntax. If typelists become enough of a first-class citizen that
> it becomes possible to introduce a typelist into scope and then expand it
> with natural syntax, then it becomes plausible that you could write:
>
> template <typename...Ts>
> std::vector<size_t> foo(Ts&& ...) { return {std::index_sequence_for<Ts
> ...>::value...}; }
>
> Here, std::integer_sequence has been augmented with a typelist holding
> its compile-time integer sequence:
>
> template<class T, T... Ints>
> struct integer_sequence {
> using value_type = T;
> using value = <Ints...>; // new typelist member after n3728;
> syntax TBD
> static constexpr std::size_t size() { return sizeof...(Ints); }
> };
>
> Does anyone know what kind of reception Mike got at Chicago when
> presenting n3728?
>
> On Monday, 20 July 2015 19:08:39 UTC+1, sco...@gmail.com wrote:
>>
>> Hi,
>>
>> Variadic template parameters are really nice, and it's really impressive
>> how complex of expressions you can unpack (with more coming once C++17
>> allows folds). However, there is currently a glaring gap in the feature:
>> you can't access the position number of a type when unpacking a parameter
>> pack. This makes it unnecessarily hard to write code that mixes parameter
>> packs and tuples, because the one works with variadic lists of types and
>> the other requires use of std::get<size_t>.
>>
>> The idea I'd like to float, then, is that the position of a given type
>> within its pack should be accessible during unpacking:
>> template <typename...Ts>
>> std::vector<size_t> foo(Ts&& ...) { return {#Ts...}; }
>>
>> int main() {
>> std::vector a{0,1,2}, b=foo("hi", "ho", "hum");
>> assert(a == b); // succeeds
>> }
>>
>> The above function is clearly a toy example, and the exact syntax need
>> not be '#Ts' but hopefully it conveys the idea. The feature would
>> complement the existing sizeof...() operator, and I do not think it would
>> be difficult to provide compiler support for it (though I am by no means a
>> compiler expert).
>>
>> The rest of this message consists of examples to show why such a syntax
>> might be useful. The first three examples were extracted from real-life
>> scenarios I encountered in my work, though they have been simplified
>> drastically here to be more concise. The last example I made up, to show
>> something that would be really unpleasant to express without the proposed
>> syntax.
>>
>> Apologies in advance if this idea has already been floated in the
>> past---a search of this forum did not turn up any obvious matches, but that
>> doesn't mean much.
>>
>> Example 1:
>> ====================
>>
>> Suppose I have some code that assigns values to a std::tuple which are
>> constructible and assignable---but not convertible---to the tuple's field
>> types. This means I can't write this:
>> template <typename T>
>> struct StoredType { using type=T; };
>>
>> /* various specializations of StoredType follow, but
>> * std::is_constructible<StoredType<T>::type, T> always holds
>> */
>> template <typename... FTs>
>> struct Foo {
>> std::tuple<typename StoredType<FTs>::type...> _data;
>>
>> Foo(FTs const & ...args) : _data{args...} { } // error!
>> };
>>
>> Instead, the constructor needs a hack like the following:
>> Foo(FTs const & ...args) { init_data<0,FTs...>(args...); }
>>
>> template <size_t M, typename T, typename... Rest>
>> void init_data(T const &arg, Rest const & ...rest) {
>> std::get<M>(_data) = arg;
>> init_data<M+1, Rest...>(rest...);
>> }
>>
>> template <size_t M, typename T>
>> void init_data(T const &arg) {
>> std::get<M>(_data) = arg;
>> }
>>
>> If there were a way to access type positions in a parameter pack, the
>> constructor hack would be much simpler and cleaner:
>> Foo(FTs const & ...args) {
>> auto x = {(std::get<#FTs>(_data)=args)...};
>> (void) x;
>> }
>>
>> (I know that N4387 will address this particular problem, but that's
>> besides the point)
>>
>> Example 2:
>> ====================
>>
>> Consider a fold function that accepts some number of inputs and applies
>> an action to each of them (vaguely similar to what C++17 is likely to
>> support). If the values to be folded are provided as arguments to a
>> variadic template function, then it's really easy (assuming C++14 generic
>> lambdas):
>> // workaround for fact that we can't make a std::initializer_list<void>
>> template <typename Action, typename T>
>> bool void_fold_one(Action &action, T &&t) {
>> action(std::forward<T>(t));
>> return true;
>> }
>>
>> template <typename Action, typename T, typename... Ts>
>> void void_fold(Action &&action, T &&t, Ts&&... args)
>> {
>> auto x = {void_fold_one(action, std::forward<T>(t))...};
>> (void) x;
>> }
>>
>> int main() {
>> auto action = [](auto x) { std::cout << x << " "; };
>> void_fold(action, 1, 3.14, "hi", std::endl);
>> }
>>
>>
>> Now try to do that with a std::tuple instead and you end up with
>> something much less satisfying:
>> template <size_t I, size_t N>
>> struct void_fold_tuple_ {
>> template <typename Action, typename Tuple>
>> static void call(Action &action, Tuple &tup)
>> {
>> action.template operator()<I>(tup);
>> using recursive = void_fold_tuple_<I+1, N>;
>> recursive::call(action, tup);
>> }
>> };
>>
>> template <size_t N>
>> struct void_fold_tuple_<N, N> {
>> template <typename Action, typename Tuple>
>> static void call(Action&, Tuple&) { /* no-op */ }
>> };
>>
>> struct print_action {
>> template <typename Tuple, size_t I>
>> void operator()(Tuple &tup) {
>> using std::get; // ADL
>> std::cout << std::get<I>(tup) << " ";
>> }
>> };
>>
>> template <typename Action, typename Tuple>
>> void void_fold_tuple(Action &&action, Tuple &&tup)
>> {
>> using std::tuple_size; // ADL
>> using tuple = typename std::remove_reference<Tuple>::type;
>> using recursive = void_fold_tuple_<0, tuple_size<tuple>::value>;
>> recursive::call(action, tup);
>> }
>>
>> int main() {
>> std::tuple<int, double, char const *> tup{1,3.14,"hi",std::endl};
>> void_fold_tuple(print_action{}, tup);
>> };
>>
>> If something like the #N syntax were available then it would simplify
>> back to something that resembles strongly the first case:
>> template <typename Action, template <typename ...> class Tuple, typename
>> ...FTs>
>> void void_fold_tuple(Action &&action, Tuple<FTs...> &&tup)
>> {
>> auto x = {void_fold_one(action, std::get<#FTs>(tup)...)};
>> (void) x;
>> }
>>
>> int main() {
>> std::tuple<int, double, char const *> tup{1, 3.14, "hi", std::endl};
>> void_fold_tuple(print_action{}, tup);
>> };
>>
>> Example 3
>> ====================
>>
>> Suppose we want to initialize the contents of a std::tuple using a
>> std::vector (this actually arose in our code when we have templated child
>> classes that specialize a virtual base class used elsewhere). Right now the
>> only way to achieve it is something like the following:
>> template<int...>
>> struct Sequence { };
>>
>> template<size_t N, size_t... S>
>> struct GenSequence {
>> using type = typename GenSequence<N-1, N-1, S...>::type;
>> };
>>
>> template<size_t... S>
>> struct GenSequence<0, S...>
>> {
>> using type = Sequence<S...>;
>> };
>>
>> template <typename... Ts>
>> struct Foo {
>> using Tuple = std::tuple<Ts* ...>;
>> using Vector = std::vector<void*>;
>> using Seq = typename GenSequence<sizeof...(Ts)>::type;
>>
>> Foo(Vector const &v) {
>> init_pointers(v, Seq());
>> }
>>
>> template <size_t ... S>
>> void init_pointers(Vector const &v, Seq) {
>> _pointers = Tuple{dynamic_cast<Ts*>(v[S])...};
>> }
>>
>> Tuple _pointers;
>> };
>>
>> With the new syntax that would simplify to:
>> template <typename... Ts>
>> struct Foo {
>> using Tuple = std::tuple<Ts* ...>;
>> using Vector = std::vector<void*>;
>>
>> Foo(Vector const &v)
>> : _pointers{dynamic_cast<Ts*>(v[#Ts])...}
>> {
>> }
>>
>> Tuple _pointers;
>> };
>>
>> Example 4
>> ====================
>>
>> Suppose I wanted to define a function that reverses the fields of a
>> tuple. With the proposed syntax it would not be difficult to write such a
>> function:
>> template <size_t M, typename T, typename... Ts>
>> struct Select{
>> using type = typename Select<M - 1, Ts...>::type;
>> };
>>
>> template <typename T, typename... Ts>
>> struct Select<0, T, Ts...>{
>> using type = T;
>> };
>>
>> template <template <typename...> class Tuple, typename... Ts>
>> auto reverse(Tuple<Ts...> const &tup) {
>> static constexpr size_t const N = sizeof...(Ts) - 1;
>> using RTuple = Tuple<typename Select<N - #Ts, Ts...>::type...>;
>> return RTuple<{std::get<N-#Ts>(tup)...};
>> }
>>
>> I'll leave the vanilla C++14 version of the above function as an exercise
>> for the reader...
>>
>> Thoughts?
>> Ryan Johnson
>>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2365_384705389.1437435386984
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Hmm. That's a very interesting proposal I didn=
9;t know about (thanks for=20
the heads-up!), but I'm not sure it actually solves the awkwardness I=
=20
was pointing out here: even if you had proper typelists, you'd still=20
need some (presumably recursive) variadic template helper(s) to convert a=
=20
`template <typename... Ts>' into a `template <size_t... Is>=
'
for cases where you need to index types. To implement this std::index_sequ=
ence_for that you mention, for example, my proposed syntax would lead to so=
mething like:</div><div class=3D"prettyprint" style=3D"border: 1px solid rg=
b(187, 187, 187); border-image: none; -ms-word-wrap: break-word; background=
-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subp=
rettyprint"><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 13=
6);">template</span><span class=3D"styled-by-prettify" style=3D"color: rgb(=
0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=3D"color: rgb(1=
02, 102, 0);"><</span><span class=3D"styled-by-prettify" style=3D"color:=
rgb(0, 0, 136);">typename</span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(102, 102, 0);">...</span><span class=3D"styled-by-prettify" =
style=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" s=
tyle=3D"color: rgb(102, 0, 102);">Ts</span><span class=3D"styled-by-prettif=
y" style=3D"color: rgb(102, 102, 0);">></span><span class=3D"styled-by-p=
rettify" style=3D"color: rgb(0, 0, 0);"><br></span><span class=3D"styled-by=
-prettify" style=3D"color: rgb(0, 0, 136);">struct</span><span class=3D"sty=
led-by-prettify" style=3D"color: rgb(0, 0, 0);"> index_sequence_for </span>=
<span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">{</sp=
an><span class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br>=
=C2=A0 =C2=A0</span><span class=3D"styled-by-prettify" style=3D"color: rgb(=
0, 0, 136);">using</span><span class=3D"styled-by-prettify" style=3D"color:=
rgb(0, 0, 0);"> value </span><span class=3D"styled-by-prettify" style=3D"c=
olor: rgb(102, 102, 0);">=3D</span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(0, 0, 0);"> </span><span class=3D"styled-by-prettify" style=
=3D"color: rgb(102, 102, 0);"><</span><span class=3D"styled-by-prettify"=
style=3D"color: rgb(136, 0, 0);">#Ts...>;</span><span class=3D"styled-b=
y-prettify" style=3D"color: rgb(0, 0, 0);"><br></span><span class=3D"styled=
-by-prettify" style=3D"color: rgb(102, 102, 0);">};</span><span class=3D"st=
yled-by-prettify" style=3D"color: rgb(0, 0, 0);"><br></span></div></code></=
div><p><br></p><div>... which is rather simpler than the alternatives I cou=
ld imagine.</div><div><br></div><div>Also, my proposed syntax would make su=
ch a class largely unnecessary because anyone wanting to turn a typelist in=
to an integer sequence could just use the same technique directly.</div><di=
v><br></div><div>Still, if the other proposal brought as a side effect the =
ability to turn type lists into integer sequences with less hoop-jumping th=
an the current status quo, I'd not complain too loudly.<br><br><br>On M=
onday, July 20, 2015 at 4:54:09 PM UTC-6, Edward Catmur wrote:</div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left=
: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; borde=
r-left-style: solid;"><div dir=3D"ltr">I think n3728 or something similar w=
ould provide what you're after, with reasonable syntax. If typelists be=
come enough of a first-class citizen that it becomes possible to introduce =
a typelist into scope and then expand it with natural syntax, then it becom=
es plausible that you could write:<div><br></div><div><div style=3D"border:=
1px solid rgb(187, 187, 187); border-image: none; -ms-word-wrap: break-wor=
d; background-color: rgb(250, 250, 250);"><code><div><span style=3D"color: =
rgb(0, 0, 136);">template</span><span style=3D"color: rgb(0, 0, 0);"> </spa=
n><span style=3D"color: rgb(102, 102, 0);"><</span><span style=3D"color:=
rgb(0, 0, 136);">typename</span><span style=3D"color: rgb(102, 102, 0);">.=
...</span><span style=3D"color: rgb(102, 0, 102);">Ts</span><span style=3D"c=
olor: rgb(102, 102, 0);">></span><span style=3D"color: rgb(0, 0, 0);"><b=
r>std</span><span style=3D"color: rgb(102, 102, 0);">::</span><span style=
=3D"color: rgb(0, 0, 0);">vector</span><span style=3D"color: rgb(0, 136, 0)=
;"><size_t></span><span style=3D"color: rgb(0, 0, 0);"> foo</span><sp=
an style=3D"color: rgb(102, 102, 0);">(</span><span style=3D"color: rgb(102=
, 0, 102);">Ts</span><span style=3D"color: rgb(102, 102, 0);">&&</s=
pan><span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(=
102, 102, 0);">...)</span><span style=3D"color: rgb(0, 0, 0);"> </span><spa=
n style=3D"color: rgb(102, 102, 0);">{</span><span style=3D"color: rgb(0, 0=
, 0);"> </span><span style=3D"color: rgb(0, 0, 136);">return</span><span st=
yle=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(102, 102, 0)=
;">{</span><span style=3D"color: rgb(0, 0, 0);">std</span><span style=3D"co=
lor: rgb(102, 102, 0);">::</span><span style=3D"color: rgb(0, 0, 0);">index=
_sequence_for</span><span style=3D"color: rgb(102, 102, 0);"><</span><sp=
an style=3D"color: rgb(102, 0, 102);">Ts</span><span style=3D"color: rgb(10=
2, 102, 0);">...>::</span><span style=3D"color: rgb(0, 0, 0);">value</sp=
an><span style=3D"color: rgb(102, 102, 0);">...};</span><span style=3D"colo=
r: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(102, 102, 0);">}</span>=
<span style=3D"color: rgb(0, 0, 0);"><br></span></div></code></div><div><br=
></div><div>Here, <font face=3D"courier new, monospace">std::integer_sequen=
ce</font> has been augmented with a typelist holding its compile-time integ=
er sequence:</div><div><br></div><div style=3D"border: 1px solid rgb(187, 1=
87, 187); border-image: none; -ms-word-wrap: break-word; background-color: =
rgb(250, 250, 250);"><code><div><span style=3D"color: rgb(0, 0, 136);">temp=
late</span><span style=3D"color: rgb(102, 102, 0);"><</span><span style=
=3D"color: rgb(0, 0, 136);">class</span><span style=3D"color: rgb(0, 0, 0);=
"> T</span><span style=3D"color: rgb(102, 102, 0);">,</span><span style=3D"=
color: rgb(0, 0, 0);"> T</span><span style=3D"color: rgb(102, 102, 0);">...=
</span><span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: r=
gb(102, 0, 102);">Ints</span><span style=3D"color: rgb(102, 102, 0);">><=
/span><span style=3D"color: rgb(0, 0, 0);"><br></span><font color=3D"#00008=
8"><span style=3D"color: rgb(0, 0, 136);">struct</span><span style=3D"color=
: rgb(0, 0, 0);"> </span></font><span style=3D"color: rgb(0, 0, 0);">intege=
r_sequence</span><font color=3D"#666600"><span style=3D"color: rgb(0, 0, 0)=
;"> </span><span style=3D"color: rgb(102, 102, 0);">{</span><span style=3D"=
color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0 </span><span style=3D"color: rgb(0,=
0, 136);">using</span><span style=3D"color: rgb(0, 0, 0);"> value_type </s=
pan><span style=3D"color: rgb(102, 102, 0);">=3D</span><span style=3D"color=
: rgb(0, 0, 0);"> T</span><span style=3D"color: rgb(102, 102, 0);">;</span>=
<span style=3D"color: rgb(0, 0, 0);"><br></span></font><span style=3D"color=
: rgb(0, 0, 0);">=C2=A0 =C2=A0 </span><span style=3D"color: rgb(0, 0, 136);=
">using</span><span style=3D"color: rgb(0, 0, 0);"> value </span><span styl=
e=3D"color: rgb(102, 102, 0);">=3D</span><span style=3D"color: rgb(0, 0, 0)=
;"> </span><span style=3D"color: rgb(102, 102, 0);"><</span><span style=
=3D"color: rgb(102, 0, 102);">Ints</span><span style=3D"color: rgb(102, 102=
, 0);">...>;</span><span style=3D"color: rgb(0, 0, 0);"> =C2=A0 =C2=A0</=
span><span style=3D"color: rgb(136, 0, 0);">// new typelist member after n3=
728; syntax TBD</span><span style=3D"color: rgb(0, 0, 0);"><br></span><font=
color=3D"#666600"><span style=3D"color: rgb(0, 0, 0);">=C2=A0 =C2=A0 </spa=
n><span style=3D"color: rgb(0, 0, 136);">static</span><span style=3D"color:=
rgb(0, 0, 0);"> </span><span style=3D"color: rgb(0, 0, 136);">constexpr</s=
pan><span style=3D"color: rgb(0, 0, 0);"> std</span><span style=3D"color: r=
gb(102, 102, 0);">::</span><span style=3D"color: rgb(0, 0, 0);">size_t size=
</span><span style=3D"color: rgb(102, 102, 0);">()</span><span style=3D"col=
or: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(102, 102, 0);">{</span=
><span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(0, =
0, 136);">return</span><span style=3D"color: rgb(0, 0, 0);"> </span><span s=
tyle=3D"color: rgb(0, 0, 136);">sizeof</span><span style=3D"color: rgb(102,=
102, 0);">...(</span><span style=3D"color: rgb(102, 0, 102);">Ints</span><=
span style=3D"color: rgb(102, 102, 0);">);</span><span style=3D"color: rgb(=
0, 0, 0);"> </span><span style=3D"color: rgb(102, 102, 0);">}</span><span s=
tyle=3D"color: rgb(0, 0, 0);"><br></span></font><span style=3D"color: rgb(1=
02, 102, 0);">};</span><span style=3D"color: rgb(0, 0, 0);"><br></span></di=
v></code></div><div><br></div><div>Does anyone know what kind of reception =
Mike got at Chicago when presenting n3728?=C2=A0<br><br>On Monday, 20 July =
2015 19:08:39 UTC+1, <a>sco...@gmail.com</a> wrote:<blockquote class=3D"gm=
ail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-le=
ft-color: rgb(204, 204, 204); border-left-width: 1px; border-left-style: so=
lid;"><div dir=3D"ltr">Hi,<br><br>Variadic template parameters are really n=
ice, and it's really
impressive how complex of expressions you can unpack (with more coming=20
once C++17 allows folds). However, there is currently a glaring gap in=20
the feature: you can't access the position number of a type when=20
unpacking a parameter pack. This makes it unnecessarily hard to write=20
code that mixes parameter packs and tuples, because the one works with=20
variadic lists of types and the other requires use of=20
std::get<size_t>.<br><br>The idea I'd like to float, then, is tha=
t the position of a given type within its pack should be accessible during =
unpacking:<div style=3D"border: 1px solid rgb(187, 187, 187); border-image:=
none; background-color: rgb(250, 250, 250);"><code><div><span style=3D"col=
or: rgb(0, 0, 136);">template</span><span style=3D"color: rgb(0, 0, 0);"> <=
/span><span style=3D"color: rgb(102, 102, 0);"><</span><span style=3D"co=
lor: rgb(0, 0, 136);">typename</span><span style=3D"color: rgb(102, 102, 0)=
;">...</span><span style=3D"color: rgb(102, 0, 102);">Ts</span><span style=
=3D"color: rgb(102, 102, 0);">></span><span style=3D"color: rgb(0, 0, 0)=
;"><br>std</span><span style=3D"color: rgb(102, 102, 0);">::</span><span st=
yle=3D"color: rgb(0, 0, 0);">vector</span><span style=3D"color: rgb(0, 136,=
0);"><size_t></span><span style=3D"color: rgb(0, 0, 0);"> foo</span>=
<span style=3D"color: rgb(102, 102, 0);">(</span><span style=3D"color: rgb(=
102, 0, 102);">Ts</span><span style=3D"color: rgb(102, 102, 0);">&&=
</span><span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: r=
gb(102, 102, 0);">...)</span><span style=3D"color: rgb(0, 0, 0);"> </span><=
span style=3D"color: rgb(102, 102, 0);">{</span><span style=3D"color: rgb(0=
, 0, 0);"> </span><span style=3D"color: rgb(0, 0, 136);">return</span><span=
style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(102, 102,=
0);">{</span><span style=3D"color: rgb(136, 0, 0);">#Ts...}; }</span><span=
style=3D"color: rgb(0, 0, 0);"><br><br></span><span style=3D"color: rgb(0,=
0, 136);">int</span><span style=3D"color: rgb(0, 0, 0);"> main</span><span=
style=3D"color: rgb(102, 102, 0);">()</span><span style=3D"color: rgb(0, 0=
, 0);"> </span><span style=3D"color: rgb(102, 102, 0);">{</span><span style=
=3D"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0std</span><span style=3D"color: =
rgb(102, 102, 0);">::</span><span style=3D"color: rgb(0, 0, 0);">vector a</=
span><span style=3D"color: rgb(102, 102, 0);">{</span><span style=3D"color:=
rgb(0, 102, 102);">0</span><span style=3D"color: rgb(102, 102, 0);">,</spa=
n><span style=3D"color: rgb(0, 102, 102);">1</span><span style=3D"color: rg=
b(102, 102, 0);">,</span><span style=3D"color: rgb(0, 102, 102);">2</span><=
span style=3D"color: rgb(102, 102, 0);">},</span><span style=3D"color: rgb(=
0, 0, 0);"> b</span><span style=3D"color: rgb(102, 102, 0);">=3D</span><spa=
n style=3D"color: rgb(0, 0, 0);">foo</span><span style=3D"color: rgb(102, 1=
02, 0);">(</span><span style=3D"color: rgb(0, 136, 0);">"hi"</spa=
n><span style=3D"color: rgb(102, 102, 0);">,</span><span style=3D"color: rg=
b(0, 0, 0);"> </span><span style=3D"color: rgb(0, 136, 0);">"ho"<=
/span><span style=3D"color: rgb(102, 102, 0);">,</span><span style=3D"color=
: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(0, 136, 0);">"hum&q=
uot;</span><span style=3D"color: rgb(102, 102, 0);">);</span><span style=3D=
"color: rgb(0, 0, 0);"><br>=C2=A0 =C2=A0</span><span style=3D"color: rgb(0,=
0, 136);">assert</span><span style=3D"color: rgb(102, 102, 0);">(</span><s=
pan style=3D"color: rgb(0, 0, 0);">a </span><span style=3D"color: rgb(102, =
102, 0);">=3D=3D</span><span style=3D"color: rgb(0, 0, 0);"> b</span><span =
style=3D"color: rgb(102, 102, 0);">);</span><span style=3D"color: rgb(0, 0,=
0);"> </span><span style=3D"color: rgb(136, 0, 0);">// succeeds</span><spa=
n style=3D"color: rgb(0, 0, 0);"><br></span><span style=3D"color: rgb(102, =
102, 0);">}</span><span style=3D"color: rgb(0, 0, 0);"><br></span></div></c=
ode></div><br>The
above function is clearly a toy example, and the exact syntax need not=20
be '#Ts' but hopefully it conveys the idea. The feature would compl=
ement
the existing sizeof...() operator, and I do not think it would be=20
difficult to provide compiler support for it (though I am by no means a=20
compiler expert).<br><br>The rest of this message consists of examples=20
to show why such a syntax might be useful. The first three examples were
extracted from real-life scenarios I encountered in my work, though=20
they have been simplified drastically here to be more concise. The last=20
example I made up, to show something that would be really unpleasant to=20
express without the proposed syntax.<br><br>Apologies in advance if this id=
ea has already been floated in the=20
past---a search of this forum did not turn up any obvious matches, but=20
that doesn't mean much.<br><br>Example 1: <br>=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br><br>Suppose
I have some code that assigns values to a std::tuple which are=20
constructible and assignable---but not convertible---to the tuple's=20
field types. This means I can't write this:<br><div style=3D"border: 1p=
x solid rgb(187, 187, 187); border-image: none; background-color: rgb(250, =
250, 250);"><code><div><span style=3D"color: rgb(0, 0, 136);">template</spa=
n><span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(10=
2, 102, 0);"><</span><span style=3D"color: rgb(0, 0, 136);">typename</sp=
an><span style=3D"color: rgb(0, 0, 0);"> T</span><span style=3D"color: rgb(=
102, 102, 0);">></span><span style=3D"color: rgb(0, 0, 0);"><br></span><=
span style=3D"color: rgb(0, 0, 136);">struct</span><span style=3D"color: rg=
b(0, 0, 0);"> </span><span style=3D"color: rgb(102, 0, 102);">StoredType</s=
pan><span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(=
102, 102, 0);">{</span><span style=3D"color: rgb(0, 0, 0);"> </span><span s=
tyle=3D"color: rgb(0, 0, 136);">using</span><span style=3D"color: rgb(0, 0,=
0);"> type</span><span style=3D"color: rgb(102, 102, 0);">=3D</span><span =
style=3D"color: rgb(0, 0, 0);">T</span><span style=3D"color: rgb(102, 102, =
0);">;</span><span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"co=
lor: rgb(102, 102, 0);">};</span><span style=3D"color: rgb(0, 0, 0);"><br><=
/span><span style=3D"color: rgb(0, 0, 0);"><br></span><span style=3D"color:=
rgb(136, 0, 0);">/* various specializations of StoredType follow, but <br>=
=C2=A0* </span><span style=3D"color: rgb(136, 0, 0);"><code><span style=3D"=
color: rgb(136, 0, 0);"><code><span style=3D"color: rgb(0, 0, 136);"><code>=
<span style=3D"color: rgb(136, 0, 0);">std::is_constructible<StoredType&=
lt;T>::type, T> always holds</span></code></span></code></span></code=
><br>=C2=A0*/</span><span style=3D"color: rgb(0, 0, 0);"><br></span><span s=
tyle=3D"color: rgb(0, 0, 136);">template</span><span style=3D"color: rgb(0,=
0, 0);"> </span><span style=3D"color: rgb(102, 102, 0);"><</span><span =
style=3D"color: rgb(0, 0, 136);">typename</span><span style=3D"color: rgb(1=
02, 102, 0);">...</span><span style=3D"color: rgb(0, 0, 0);"> </span><span =
style=3D"color: rgb(102, 0, 102);">FTs</span><span style=3D"color: rgb(102,=
102, 0);">></span><span style=3D"color: rgb(0, 0, 0);"><br></span><span=
style=3D"color: rgb(0, 0, 136);">struct</span><span style=3D"color: rgb(0,=
0, 0);"> </span><span style=3D"color: rgb(102, 0, 102);">Foo</span><span s=
tyle=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(102, 102, 0=
);">{</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0=C2=A0 std::tupl=
e<typename StoredType<FTs>::type...> _data;<br><br>=C2=A0 =C2=
=A0</span><span style=3D"color: rgb(102, 0, 102);">Foo</span><span style=3D=
"color: rgb(102, 102, 0);">(</span><span style=3D"color: rgb(102, 0, 102);"=
>FTs</span><span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"colo=
r: rgb(0, 0, 136);">const</span><span style=3D"color: rgb(0, 0, 0);"> </spa=
n><span style=3D"color: rgb(102, 102, 0);">&</span><span style=3D"color=
: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(102, 102, 0);">...</span=
><span style=3D"color: rgb(0, 0, 0);">args</span><span style=3D"color: rgb(=
102, 102, 0);">)</span><span style=3D"color: rgb(0, 0, 0);"> </span><span s=
tyle=3D"color: rgb(102, 102, 0);">:</span><span style=3D"color: rgb(0, 0, 0=
);"> _data{args...} { } // error!<br></span><span style=3D"color: rgb(102, =
102, 0);">};</span><span style=3D"color: rgb(0, 0, 0);"><br></span></div></=
code></div><br>Instead, the constructor needs a hack like the following:<br=
><div style=3D"border: 1px solid rgb(187, 187, 187); border-image: none; ba=
ckground-color: rgb(250, 250, 250);"><code><div><span style=3D"color: rgb(1=
02, 0, 102);">Foo(FTs const & ...args) { init_data<0,FTs...>(args=
....); }</span><span style=3D"color: rgb(102, 102, 0);"></span><br><br>templ=
ate <size_t M, typename T, typename... Rest><br>void init_data(T cons=
t &arg, Rest const & ...rest) {<br>=C2=A0=C2=A0 std::get<M>(_=
data) =3D arg;<br>=C2=A0=C2=A0 init_data<M+1, Rest...>(rest...);<br>}=
<br><br>template <size_t M, typename T><br>void init_data(T const &am=
p;arg) {<br>=C2=A0=C2=A0 std::get<M>(_data) =3D arg;<br>}<br></div></=
code></div><br>If there were a way to access type positions in a parameter =
pack, the constructor hack would be much simpler and cleaner:<br><div style=
=3D"border: 1px solid rgb(187, 187, 187); border-image: none; background-co=
lor: rgb(250, 250, 250);"><code><div><span style=3D"color: rgb(102, 0, 102)=
;">Foo(FTs const & ...args) { <br>=C2=A0=C2=A0 auto x =3D {(std::get<=
;#FTs>(_data)=3Dargs)...}; <br>=C2=A0=C2=A0 (void) x;<br>}<br></span></d=
iv></code></div><br>(I know that N4387 will address this particular proble=
m, but that's besides the point)<br><br>Example 2: <br>=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br><br>Consider
a fold function that accepts some number of inputs and applies an=20
action to each of them (vaguely similar to what C++17 is likely to=20
support). If the values to be folded are provided as arguments to a=20
variadic template function, then it's really easy (assuming C++14=20
generic lambdas):<br><div style=3D"border: 1px solid rgb(187, 187, 187); bo=
rder-image: none; background-color: rgb(250, 250, 250);"><code><div><span s=
tyle=3D"color: rgb(102, 0, 102);"><code>// workaround for fact that we can&=
#39;t make a std::initializer_list<void><br>template <typename Act=
ion, typename T><br>bool void_fold_one(Action &action, T &&t=
) {<br>=C2=A0=C2=A0 action(std::forward<T>(t));<br>=C2=A0=C2=A0 retur=
n true;<br>}<br><br></code>template <typename Action, typename T, typena=
me... Ts><br>void void_fold(Action &&action, T &&t, Ts&a=
mp;&... args)<br>{<br>=C2=A0=C2=A0 auto x =3D {void_fold_one(action, st=
d::forward<T>(t))...};<br>=C2=A0=C2=A0 (void) x;<br>}<br><br>int main=
() {<br>=C2=A0=C2=A0 auto action =3D [](auto x) { std::cout << x <=
< " "; };<br>=C2=A0=C2=A0 void_fold(action, 1, 3.14, "hi&=
quot;, std::endl);<br>}<br></span><span style=3D"color: rgb(102, 102, 0);">=
</span></div></code></div><code></code><br><br>Now try to do that with a st=
d::tuple instead and you end up with something much less satisfying:<br><di=
v style=3D"border: 1px solid rgb(187, 187, 187); border-image: none; backgr=
ound-color: rgb(250, 250, 250);"><code><div><span style=3D"color: rgb(102, =
0, 102);">template <size_t I, size_t N><br>struct void_fold_tuple_ {<=
br>=C2=A0=C2=A0 template <typename Action, typename Tuple><br>=C2=A0=
=C2=A0 static void call(Action &action, Tuple &tup)<br>=C2=A0=C2=A0=
{<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 action.template operator()<I>(tu=
p);<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 using recursive =3D void_fold_tuple_&=
lt;I+1, N>;<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 recursive::call(action, tu=
p);<br>=C2=A0=C2=A0 }<br>};<br><br>template <size_t N><br>struct void=
_fold_tuple_<N, N> {<br>=C2=A0=C2=A0 template <typename Action, ty=
pename Tuple><br>=C2=A0=C2=A0 static void call(Action&, Tuple&) =
{ /* no-op */ }<br>};<br><br>struct print_action {<br>=C2=A0=C2=A0 template=
<typename Tuple, size_t I><br>=C2=A0=C2=A0 void operator()(Tuple &am=
p;tup) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 using std::get; // ADL<br>=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 std::cout << std::get<I>(tup) <<=
" ";<br>=C2=A0=C2=A0 }<br>};<br><br>template <typename Action=
, typename Tuple><br>void void_fold_tuple(Action &&action, Tuple=
&&tup)<br>{<br>=C2=A0=C2=A0 using std::tuple_size; // ADL<br>=C2=
=A0=C2=A0 using tuple =3D typename std::remove_reference<Tuple>::type=
;<br>=C2=A0=C2=A0 using recursive =3D void_fold_tuple_<0, tuple_size<=
tuple>::value>;<br>=C2=A0=C2=A0 recursive::call(action, tup);<br>}<br=
><br>int main() {<br>=C2=A0=C2=A0 std::tuple<int, double, char const *&g=
t; tup{1,3.14,"hi",std::endl};<br></span><span style=3D"color: rg=
b(102, 0, 102);"><code><code><span style=3D"color: rgb(102, 0, 102);">=C2=
=A0=C2=A0 void_fold_tuple(print_action{}, tup);<br></span></code></code>};<=
br></span><span style=3D"color: rgb(102, 102, 0);"></span></div></code></di=
v><br>If something like the #N syntax were available then it would simplify=
back to something that resembles strongly the first case:<br><div style=3D=
"border: 1px solid rgb(187, 187, 187); border-image: none; background-color=
: rgb(250, 250, 250);"><code><div><span style=3D"color: rgb(102, 0, 102);">=
</span><code><span style=3D"color: rgb(102, 0, 102);">template <typename=
Action, template <typename ...> class Tuple, typename ...FTs><br>=
void void_fold_tuple(Action &&action, Tuple<FTs...> &&=
;tup)<br>{<br>=C2=A0=C2=A0 auto x =3D {void_fold_one(action, std::get<#F=
Ts>(tup)...)};<br>=C2=A0=C2=A0 (void) x;<br>}<br><br>int main() {<br>=C2=
=A0=C2=A0 std::tuple<int, double, char const *> tup{1, 3.14, "hi=
", std::endl};<br>=C2=A0=C2=A0 void_fold_tuple(print_action{}, tup);<b=
r>};</span></code></div></code></div><br>Example 3<br>=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br><br>Suppose
we want to initialize the contents of a std::tuple using a std::vector=20
(this actually arose in our code when we have templated child classes=20
that specialize a virtual base class used elsewhere). Right now the only
way to achieve it is something like the following:<br><div style=3D"border=
: 1px solid rgb(187, 187, 187); border-image: none; background-color: rgb(2=
50, 250, 250);"><code><div><span style=3D"color: rgb(102, 0, 102);">templat=
e<int...><br>struct Sequence { };<br><br>template<size_t N, </span=
><span style=3D"color: rgb(102, 0, 102);"><code><span style=3D"color: rgb(1=
02, 0, 102);">size_t</span></code>... S><br>struct GenSequence {<br>=C2=
=A0=C2=A0 using type =3D typename GenSequence<N-1, N-1, S...>::type;<=
br>};<br><br>template<</span><span style=3D"color: rgb(102, 0, 102);"><c=
ode><span style=3D"color: rgb(102, 0, 102);">size_t</span></code>... S><=
br>struct GenSequence<0, S...><br>{<br>=C2=A0=C2=A0 using type =3D Se=
quence<S...>;<br>};<br><br>template <typename... Ts><br>struct =
Foo {<br>=C2=A0=C2=A0 using Tuple =3D </span><span style=3D"color: rgb(102,=
0, 102);"><code><span style=3D"color: rgb(102, 0, 102);">std::tuple<Ts*=
...>;<br>=C2=A0=C2=A0 using Vector =3D std::vector<void*>;<br></s=
pan></code> =C2=A0=C2=A0 using Seq =3D typename GenSequence<sizeof...(Ts=
)>::type;<br><br>=C2=A0=C2=A0 Foo(Vector const &v) {<br>=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 init_pointers(v, Seq());<br>=C2=A0=C2=A0 }<br><br>=C2=A0=
=C2=A0 template <size_t ... S><br>=C2=A0=C2=A0 void init_pointers(Vec=
tor const &v, Seq) {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 _pointers =3D Tu=
ple{dynamic_cast<Ts*>(v[S])...};<br>=C2=A0=C2=A0 }<br><br>=C2=A0=C2=
=A0 Tuple _pointers;<br>};<br></span><span style=3D"color: rgb(102, 102, 0)=
;"></span></div></code></div><br>With the new syntax that would simplify to=
:<br><div style=3D"border: 1px solid rgb(187, 187, 187); border-image: none=
; background-color: rgb(250, 250, 250);"><code><div><code><span style=3D"co=
lor: rgb(102, 0, 102);">template <typename... Ts><br>struct Foo {<br>=
=C2=A0=C2=A0 using Tuple =3D </span><span style=3D"color: rgb(102, 0, 102);=
"><code><span style=3D"color: rgb(102, 0, 102);">std::tuple<Ts* ...>;=
<br>=C2=A0=C2=A0 using Vector =3D std::vector<void*>;<br></span></cod=
e><br>=C2=A0=C2=A0 Foo(Vector const &v) <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 : _pointers{dynamic_cast<Ts*>(v[#Ts])...}<br>=C2=A0=C2=A0 {<br>=
=C2=A0=C2=A0 }<br><br>=C2=A0=C2=A0 Tuple _pointers;<br>};<br></span></code>=
<span style=3D"color: rgb(102, 102, 0);"></span></div></code></div><br>Exam=
ple 4<br>=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br><b=
r>Suppose
I wanted to define a function that reverses the fields of a tuple. With
the proposed syntax it would not be difficult to write such a function:<br=
><div style=3D"border: 1px solid rgb(187, 187, 187); border-image: none; ba=
ckground-color: rgb(250, 250, 250);"><code><div><span style=3D"color: rgb(1=
02, 0, 102);">template <size_t M, typename T, typename... Ts><br>stru=
ct Select{<br>=C2=A0=C2=A0=C2=A0 using type =3D typename Select<M - 1, T=
s...>::type;<br>};<br><br>template <typename T, typename... Ts><br=
>struct Select<0, T, Ts...>{<br>=C2=A0=C2=A0=C2=A0 using type =3D T;<=
br>};<br><br>template <template <typename...> class Tuple, typenam=
e... Ts><br>auto reverse(Tuple<Ts...> const &tup) {<br>=C2=A0=
=C2=A0 static constexpr size_t const N =3D </span><span style=3D"color: rgb=
(102, 0, 102);"><code><span style=3D"color: rgb(102, 0, 102);"><code><span =
style=3D"color: rgb(102, 0, 102);">sizeof...(Ts) - 1;</span></code></span><=
/code><br>=C2=A0=C2=A0 using RTuple =3D </span><span style=3D"color: rgb(10=
2, 0, 102);"><code><span style=3D"color: rgb(102, 0, 102);">Tuple<typena=
me Select<N - #Ts, Ts...>::type...>;<br>=C2=A0</span></code>=C2=A0=
return RTuple<{std::get<N-#Ts>(tup)...};<br>}<br></span><span sty=
le=3D"color: rgb(102, 102, 0);"></span></div></code></div><br>I'll leav=
e the vanilla C++14 version of the above function as an exercise for the re=
ader...<br><br>Thoughts?<br>Ryan Johnson</div></blockquote></div></div></di=
v></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2365_384705389.1437435386984--
------=_Part_2364_1422965832.1437435386983--
.
Author: David Krauss <potswa@gmail.com>
Date: Wed, 22 Jul 2015 16:14:59 +0800
Raw View
--Apple-Mail=_6ADEC167-29B0-4333-B26F-D7A1656C7817
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9307=E2=80=9321, at 2:08 AM, scovich@gmail.com wrote:
>=20
> The idea I'd like to float, then, is that the position of a given type wi=
thin its pack should be accessible during unpacking:
> template <typename...Ts>
> std::vector<size_t> foo(Ts&& ...) { return {#Ts...}; }
How about a special alias template, like this:
template< typename type, std::size_t index >
using indexed_type =3D type; // Compiler magic deduces index, too
template <typename ... Ts, std::size_t ... Xs>
std::vector<std::size_t> foo( std::indexed_type< Ts, Xs > && ...) { return =
{Xs...}; }
An alias template can produce a deduced context as its result. Rather than =
introducing a new operator syntax for pack indexes, the library can encapsu=
late the =E2=80=9Coperator.=E2=80=9D The standard only needs to say that in=
dex arguments are a deduced context when indexed_type is used in a pack pat=
tern.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_6ADEC167-29B0-4333-B26F-D7A1656C7817
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9307=
=E2=80=9321, at 2:08 AM, <a href=3D"mailto:scovich@gmail.com" class=3D"">sc=
ovich@gmail.com</a> wrote:</div><br class=3D"Apple-interchange-newline"><di=
v class=3D""><span style=3D"font-family: Helvetica; font-size: 12px; font-s=
tyle: normal; font-variant: normal; font-weight: normal; letter-spacing: no=
rmal; line-height: normal; orphans: auto; text-align: start; text-indent: 0=
px; text-transform: none; white-space: normal; widows: auto; word-spacing: =
0px; -webkit-text-stroke-width: 0px; float: none; display: inline !importan=
t;" class=3D"">The idea I'd like to float, then, is that the position of a =
given type within its pack should be accessible during unpacking:</span><di=
v class=3D"prettyprint" style=3D"font-family: Helvetica; font-size: 12px; f=
ont-style: normal; font-variant: normal; font-weight: normal; letter-spacin=
g: normal; line-height: normal; orphans: auto; text-align: start; text-inde=
nt: 0px; text-transform: none; white-space: normal; widows: auto; word-spac=
ing: 0px; -webkit-text-stroke-width: 0px; border: 1px solid rgb(187, 187, 1=
87); border-image-source: none; background-color: rgb(250, 250, 250);"><cod=
e class=3D"prettyprint"><span class=3D"styled-by-prettify" style=3D"color: =
rgb(0, 0, 136);">template</span> <span class=3D"styled-by-prettify" st=
yle=3D"color: rgb(102, 102, 0);"><</span><span class=3D"styled-by-pretti=
fy" style=3D"color: rgb(0, 0, 136);">typename</span><span class=3D"styled-b=
y-prettify" style=3D"color: rgb(102, 102, 0);">...</span><span class=3D"sty=
led-by-prettify" style=3D"color: rgb(102, 0, 102);">Ts</span><span class=3D=
"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">></span><br clas=
s=3D"">std<span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, =
0);">::</span>vector<span class=3D"styled-by-prettify" style=3D"color: rgb(=
0, 136, 0);"><size_t></span><span class=3D"Apple-converted-space">&nb=
sp;</span>foo<span class=3D"styled-by-prettify" style=3D"color: rgb(102, 10=
2, 0);">(</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102,=
0, 102);">Ts</span><span class=3D"styled-by-prettify" style=3D"color: rgb(=
102, 102, 0);">&&</span> <span class=3D"styled-by-prettify" st=
yle=3D"color: rgb(102, 102, 0);">...)</span> <span class=3D"styled-by-=
prettify" style=3D"color: rgb(102, 102, 0);">{</span> <span class=3D"s=
tyled-by-prettify" style=3D"color: rgb(0, 0, 136);">return</span> <spa=
n class=3D"styled-by-prettify" style=3D"color: rgb(102, 102, 0);">{</span><=
span class=3D"styled-by-prettify" style=3D"color: rgb(136, 0, 0);">#Ts...};=
}</span><br class=3D""></code></div></div></blockquote></div><br class=3D"=
"><div class=3D"">How about a special alias template, like this:</div><div =
class=3D""><br class=3D""></div><div class=3D""><font face=3D"Courier" clas=
s=3D"">template< typename type, std::size_t index ></font></div><div =
class=3D""><font face=3D"Courier" class=3D"">using indexed_type =3D type; /=
/ Compiler magic deduces index, too</font></div><div class=3D""><font face=
=3D"Courier" class=3D""><br class=3D""></font></div><div class=3D""><font f=
ace=3D"Courier" class=3D"">template <typename ... Ts, std=
::size_t ... Xs><br class=3D"">std::vector<std::size_t> foo( =
std::indexed_type< Ts, Xs > && ...) {&nbs=
p;return {Xs...}; }<br class=3D""></font><br class=3D""></div><div cla=
ss=3D"">An alias template can produce a deduced context as its result. Rath=
er than introducing a new operator syntax for pack indexes, the library can=
encapsulate the =E2=80=9Coperator.=E2=80=9D The standard only needs to say=
that <font face=3D"Courier" class=3D"">index</font> arguments are a deduce=
d context when <font face=3D"Courier" class=3D"">indexed_type</font> is use=
d in a pack pattern.</div><div class=3D""><br class=3D""></div></body></htm=
l>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_6ADEC167-29B0-4333-B26F-D7A1656C7817--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Wed, 22 Jul 2015 06:42:34 -0600
Raw View
This is a multi-part message in MIME format.
--------------080501060401080605050404
Content-Type: text/plain; charset=UTF-8; format=flowed
Update: I have successfully implemented the feature in clang-3.8, by way
of a new builtin `__indexof()' that takes an unexpanded parameter pack
and expands to a sequence of size_t. Combined with C++17 fold
expressions, a lot of messy code at work suddenly becomes enormously
simpler.
For example, the following compiles and produces the expected result
with the hacked clang:
|
template<typenameT>
inthash(T const&t);
/* ^^^ to be specialized for lots of types */
template<template<typename...>classTuple,typename...T>
inthash(Tuple<T...>const&tup)
{
usingstd::get;// ADL
return(...^hash(get<__indexof(T)>(tup)));
}
|
Thoughts?
Ryan
On 20/07/2015 12:08 PM, scovich@gmail.com wrote:
> Hi,
>
> Variadic template parameters are really nice, and it's really
> impressive how complex of expressions you can unpack (with more coming
> once C++17 allows folds). However, there is currently a glaring gap in
> the feature: you can't access the position number of a type when
> unpacking a parameter pack. This makes it unnecessarily hard to write
> code that mixes parameter packs and tuples, because the one works with
> variadic lists of types and the other requires use of std::get<size_t>.
>
> The idea I'd like to float, then, is that the position of a given type
> within its pack should be accessible during unpacking:
> |
> template<typename...Ts>
> std::vector<size_t>foo(Ts&&...){return{#Ts...}; }
>
> intmain(){
> std::vector a{0,1,2},b=foo("hi","ho","hum");
> assert(a ==b);// succeeds
> }
> |
>
> The above function is clearly a toy example, and the exact syntax need
> not be '#Ts' but hopefully it conveys the idea. The feature would
> complement the existing sizeof...() operator, and I do not think it
> would be difficult to provide compiler support for it (though I am by
> no means a compiler expert).
>
> The rest of this message consists of examples to show why such a
> syntax might be useful. The first three examples were extracted from
> real-life scenarios I encountered in my work, though they have been
> simplified drastically here to be more concise. The last example I
> made up, to show something that would be really unpleasant to express
> without the proposed syntax.
>
> Apologies in advance if this idea has already been floated in the
> past---a search of this forum did not turn up any obvious matches, but
> that doesn't mean much.
>
> Example 1:
> ====================
>
> Suppose I have some code that assigns values to a std::tuple which are
> constructible and assignable---but not convertible---to the tuple's
> field types. This means I can't write this:
> |
> template<typenameT>
> structStoredType{usingtype=T;};
>
> /* various specializations of StoredType follow, but
> * |||std::is_constructible<StoredType<T>::type, T> always holds|||
> */
> template<typename...FTs>
> structFoo{
> std::tuple<typename StoredType<FTs>::type...> _data;
>
> Foo(FTsconst&...args):_data{args...} { } // error!
> };
> |
>
> Instead, the constructor needs a hack like the following:
> |
> Foo(FTs const & ...args) { init_data<0,FTs...>(args...); }
>
> template <size_t M, typename T, typename... Rest>
> void init_data(T const &arg, Rest const & ...rest) {
> std::get<M>(_data) = arg;
> init_data<M+1, Rest...>(rest...);
> }
>
> template <size_t M, typename T>
> void init_data(T const &arg) {
> std::get<M>(_data) = arg;
> }
> |
>
> If there were a way to access type positions in a parameter pack, the
> constructor hack would be much simpler and cleaner:
> |
> Foo(FTs const & ...args) {
> auto x = {(std::get<#FTs>(_data)=args)...};
> (void) x;
> }
> |
>
> (I know that N4387 will address this particular problem, but that's
> besides the point)
>
> Example 2:
> ====================
>
> Consider a fold function that accepts some number of inputs and
> applies an action to each of them (vaguely similar to what C++17 is
> likely to support). If the values to be folded are provided as
> arguments to a variadic template function, then it's really easy
> (assuming C++14 generic lambdas):
> |
> |// workaround for fact that we can't make a std::initializer_list<void>
> template <typename Action, typename T>
> bool void_fold_one(Action &action, T &&t) {
> action(std::forward<T>(t));
> return true;
> }
>
> |template <typename Action, typename T, typename... Ts>
> void void_fold(Action &&action, T &&t, Ts&&... args)
> {
> auto x = {void_fold_one(action, std::forward<T>(t))...};
> (void) x;
> }
>
> int main() {
> auto action = [](auto x) { std::cout << x << " "; };
> void_fold(action, 1, 3.14, "hi", std::endl);
> }
> |
> ||
>
> Now try to do that with a std::tuple instead and you end up with
> something much less satisfying:
> |
> template <size_t I, size_t N>
> struct void_fold_tuple_ {
> template <typename Action, typename Tuple>
> static void call(Action &action, Tuple &tup)
> {
> action.template operator()<I>(tup);
> using recursive = void_fold_tuple_<I+1, N>;
> recursive::call(action, tup);
> }
> };
>
> template <size_t N>
> struct void_fold_tuple_<N, N> {
> template <typename Action, typename Tuple>
> static void call(Action&, Tuple&) { /* no-op */ }
> };
>
> struct print_action {
> template <typename Tuple, size_t I>
> void operator()(Tuple &tup) {
> using std::get; // ADL
> std::cout << std::get<I>(tup) << " ";
> }
> };
>
> template <typename Action, typename Tuple>
> void void_fold_tuple(Action &&action, Tuple &&tup)
> {
> using std::tuple_size; // ADL
> using tuple = typename std::remove_reference<Tuple>::type;
> using recursive = void_fold_tuple_<0, tuple_size<tuple>::value>;
> recursive::call(action, tup);
> }
>
> int main() {
> std::tuple<int, double, char const *> tup{1,3.14,"hi",std::endl};
> ||void_fold_tuple(print_action{}, tup);
> ||};
> |
>
> If something like the #N syntax were available then it would simplify
> back to something that resembles strongly the first case:
> |
> |template <typename Action, template <typename ...> class Tuple,
> typename ...FTs>
> void void_fold_tuple(Action &&action, Tuple<FTs...> &&tup)
> {
> auto x = {void_fold_one(action, std::get<#FTs>(tup)...)};
> (void) x;
> }
>
> int main() {
> std::tuple<int, double, char const *> tup{1, 3.14, "hi", std::endl};
> void_fold_tuple(print_action{}, tup);
> };|
> |
>
> Example 3
> ====================
>
> Suppose we want to initialize the contents of a std::tuple using a
> std::vector (this actually arose in our code when we have templated
> child classes that specialize a virtual base class used elsewhere).
> Right now the only way to achieve it is something like the following:
> |
> template<int...>
> struct Sequence { };
>
> template<size_t N, |size_t|... S>
> struct GenSequence {
> using type = typename GenSequence<N-1, N-1, S...>::type;
> };
>
> template<|size_t|... S>
> struct GenSequence<0, S...>
> {
> using type = Sequence<S...>;
> };
>
> template <typename... Ts>
> struct Foo {
> using Tuple = |std::tuple<Ts* ...>;
> using Vector = std::vector<void*>;
> | using Seq = typename GenSequence<sizeof...(Ts)>::type;
>
> Foo(Vector const &v) {
> init_pointers(v, Seq());
> }
>
> template <size_t ... S>
> void init_pointers(Vector const &v, Seq) {
> _pointers = Tuple{dynamic_cast<Ts*>(v[S])...};
> }
>
> Tuple _pointers;
> };
> |
>
> With the new syntax that would simplify to:
> |
> |template <typename... Ts>
> struct Foo {
> using Tuple = |std::tuple<Ts* ...>;
> using Vector = std::vector<void*>;
> |
> Foo(Vector const &v)
> : _pointers{dynamic_cast<Ts*>(v[#Ts])...}
> {
> }
>
> Tuple _pointers;
> };
> |
> |
>
> Example 4
> ====================
>
> Suppose I wanted to define a function that reverses the fields of a
> tuple. With the proposed syntax it would not be difficult to write
> such a function:
> |
> template <size_t M, typename T, typename... Ts>
> struct Select{
> using type = typename Select<M - 1, Ts...>::type;
> };
>
> template <typename T, typename... Ts>
> struct Select<0, T, Ts...>{
> using type = T;
> };
>
> template <template <typename...> class Tuple, typename... Ts>
> auto reverse(Tuple<Ts...> const &tup) {
> static constexpr size_t const N = ||sizeof...(Ts) - 1;||
> using RTuple = |Tuple<typename Select<N - #Ts, Ts...>::type...>;
> | return RTuple<{std::get<N-#Ts>(tup)...};
> }
> |
>
> I'll leave the vanilla C++14 version of the above function as an
> exercise for the reader...
>
> Thoughts?
> Ryan Johnson
> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/u9XLfRCKzGc/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> std-proposals+unsubscribe@isocpp.org
> <mailto:std-proposals+unsubscribe@isocpp.org>.
> To post to this group, send email to std-proposals@isocpp.org
> <mailto:std-proposals@isocpp.org>.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--------------080501060401080605050404
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">
<div>Update: I have successfully implemented the feature in
clang-3.8, by way of a new builtin `__indexof()' that takes an
unexpanded parameter pack and expands to a sequence of size_t.
Combined with C++17 fold expressions, a lot of messy code at
work suddenly becomes enormously simpler. </div>
<div><br>
</div>
<div>For example, the following compiles and produces the expected
result with the hacked clang:</div>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> =
</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);"><</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">typename</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> =
T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0=
,
0, 136);">int</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> hash</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">T </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);"=
>const</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> =
</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">&</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">t</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">);</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(136, 0, 0);">/* ^^^ to be specialized for lots of
types */</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
<br>
</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0=
,
0, 136);">template</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);"><</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> =
</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);"><</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">typename</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">...></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);"=
>class</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> =
</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0,
102);">Tuple</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">,</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> =
</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);"=
>typename</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">...</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color: rgb(0=
,
0, 136);">int</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> hash</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 0, 102);">Tuple</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);"><</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">...></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);"=
>const</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> =
</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">&</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">tup</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">)</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">{</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><=
br>
=C2=A0 =C2=A0</span><span class=3D"styled-by-prettify" style=
=3D"color:
rgb(0, 0, 136);">using</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);">
std</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">::</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);"=
>get</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">;</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(136, 0, 0);"=
>//
ADL</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 0);"><br>
=C2=A0 =C2=A0</span><span class=3D"styled-by-prettify" style=
=3D"color:
rgb(0, 0, 136);">return</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"> =
</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">(...</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">^</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> hash</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">get</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);"><</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">__indexof</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">)>(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">tup</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">)));</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">}</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"><=
br>
</span></div>
</code></div>
<div><br>
Thoughts?</div>
<div>Ryan</div>
<br>
On 20/07/2015 12:08 PM, <a class=3D"moz-txt-link-abbreviated" href=3D=
"mailto:scovich@gmail.com">scovich@gmail.com</a> wrote:<br>
</div>
<blockquote
cite=3D"mid:76f19451-bc37-4125-8193-f69b0f149fd9@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">Hi,<br>
<br>
Variadic template parameters are really nice, and it's really
impressive how complex of expressions you can unpack (with more
coming once C++17 allows folds). However, there is currently a
glaring gap in the feature: you can't access the position number
of a type when unpacking a parameter pack. This makes it
unnecessarily hard to write code that mixes parameter packs and
tuples, because the one works with variadic lists of types and
the other requires use of std::get<size_t>.<br>
<br>
The idea I'd like to float, then, is that the position of a
given type within its pack should be accessible during
unpacking:
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"><</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">typename</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">...</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0,
102);">Ts</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">></span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
><br>
std</span><span class=3D"styled-by-prettify" style=3D"color=
:
rgb(102, 102, 0);">::</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>vector</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 136,
0);"><size_t></span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
foo</span><span class=3D"styled-by-prettify" style=3D"color=
:
rgb(102, 102, 0);">(</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0,
102);">Ts</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">&&</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">...)</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">{</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">return</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">{</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(136, 0,
0);">#Ts...}; }</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
<br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">int</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
main</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">()</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">{</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
><br>
=C2=A0 =C2=A0std</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">::</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>vector
a</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">{</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 102,
102);">0</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">,</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 102,
102);">1</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">,</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 102,
102);">2</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">},</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
b</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">=3D</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>foo</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 136, 0);">"hi"</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">,</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 136,
0);">"ho"</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">,</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 136, 0);">"hum"</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">);</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
=C2=A0 =C2=A0</span><span class=3D"styled-by-prettify" styl=
e=3D"color:
rgb(0, 0, 136);">assert</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">a </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">=3D=3D</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> b</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">);</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(136, 0,
0);">// succeeds</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">}</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
><br>
</span></div>
</code></div>
<br>
The above function is clearly a toy example, and the exact
syntax need not be '#Ts' but hopefully it conveys the idea. The
feature would complement the existing sizeof...() operator, and
I do not think it would be difficult to provide compiler support
for it (though I am by no means a compiler expert).<br>
<br>
The rest of this message consists of examples to show why such a
syntax might be useful. The first three examples were extracted
from real-life scenarios I encountered in my work, though they
have been simplified drastically here to be more concise. The
last example I made up, to show something that would be really
unpleasant to express without the proposed syntax.<br>
<br>
Apologies in advance if this idea has already been floated in
the past---a search of this forum did not turn up any obvious
matches, but that doesn't mean much.<br>
<br>
Example 1: <br>
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br>
<br>
Suppose I have some code that assigns values to a std::tuple
which are constructible and assignable---but not
convertible---to the tuple's field types. This means I can't
write this:<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"><</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">typename</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">struct</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 0, 102);">StoredType</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">{</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">using</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
type</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">=3D</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">;</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">};</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(136, 0, 0);">/* various specializations of
StoredType follow, but <br>
=C2=A0* </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(136, 0, 0);"><code class=3D"prettyprint=
"><span
class=3D"styled-by-prettify" style=3D"color: rgb(136, 0=
,
0);"><code class=3D"prettyprint"><span
class=3D"styled-by-prettify" style=3D"color: rgb(0,
0, 136);"><code class=3D"prettyprint"><span
class=3D"styled-by-prettify" style=3D"color:
rgb(136, 0, 0);">std::is_constructible<Store=
dType<T>::type,
T> always holds</span></code></span></code><=
/span></code><br>
=C2=A0*/</span><span class=3D"styled-by-prettify" style=3D"=
color:
rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"><</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">typename</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">...</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 0, 102);">FTs</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">struct</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 0, 102);">Foo</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">{</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
><br>
=C2=A0=C2=A0 std::tuple<typename
StoredType<FTs>::type...> _data;<br>
<br>
=C2=A0 =C2=A0</span><span class=3D"styled-by-prettify" styl=
e=3D"color:
rgb(102, 0, 102);">Foo</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 0, 102);">FTs</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">const</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">&</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">...</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>args</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">)</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">:</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> _data{args...} { } //
error!<br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">};</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
><br>
</span></div>
</code></div>
<br>
Instead, the constructor needs a hack like the following:<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(102, 0, 102);">Foo(FTs const &
...args) { init_data<0,FTs...>(args...); }</span><spa=
n
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);"></span><br>
<br>
template <size_t M, typename T, typename... Rest><br>
void init_data(T const &arg, Rest const & ...rest)
{<br>
=C2=A0=C2=A0 std::get<M>(_data) =3D arg;<br>
=C2=A0=C2=A0 init_data<M+1, Rest...>(rest...);<br>
}<br>
<br>
template <size_t M, typename T><br>
void init_data(T const &arg) {<br>
=C2=A0=C2=A0 std::get<M>(_data) =3D arg;<br>
}<br>
</div>
</code></div>
<br>
If there were a way to access type positions in a parameter
pack, the constructor hack would be much simpler and cleaner:<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(102, 0, 102);">Foo(FTs const &
...args) { <br>
=C2=A0=C2=A0 auto x =3D {(std::get<#FTs>(_data)=3Darg=
s)...}; <br>
=C2=A0=C2=A0 (void) x;<br>
}<br>
</span></div>
</code></div>
<br>
(I know that N4387 will address this particular problem, but
that's besides the point)<br>
<br>
Example 2: <br>
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br>
<br>
Consider a fold function that accepts some number of inputs and
applies an action to each of them (vaguely similar to what C++17
is likely to support). If the values to be folded are provided
as arguments to a variadic template function, then it's really
easy (assuming C++14 generic lambdas):<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(102, 0, 102);"><code
class=3D"prettyprint">// workaround for fact that we
can't make a std::initializer_list<void><br>
template <typename Action, typename T><br>
bool void_fold_one(Action &action, T &&t)
{<br>
=C2=A0=C2=A0 action(std::forward<T>(t));<br>
=C2=A0=C2=A0 return true;<br>
}<br>
<br>
</code>template <typename Action, typename T,
typename... Ts><br>
void void_fold(Action &&action, T &&t,
Ts&&... args)<br>
{<br>
=C2=A0=C2=A0 auto x =3D {void_fold_one(action,
std::forward<T>(t))...};<br>
=C2=A0=C2=A0 (void) x;<br>
}<br>
<br>
int main() {<br>
=C2=A0=C2=A0 auto action =3D [](auto x) { std::cout <<=
; x
<< " "; };<br>
=C2=A0=C2=A0 void_fold(action, 1, 3.14, "hi", std::endl);<b=
r>
}<br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"></span></div>
</code></div>
<code class=3D"prettyprint"></code><br>
<br>
Now try to do that with a std::tuple instead and you end up with
something much less satisfying:<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(102, 0, 102);">template <size_t I,
size_t N><br>
struct void_fold_tuple_ {<br>
=C2=A0=C2=A0 template <typename Action, typename Tuple&g=
t;<br>
=C2=A0=C2=A0 static void call(Action &action, Tuple &am=
p;tup)<br>
=C2=A0=C2=A0 {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 action.template operator()&l=
t;I>(tup);<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 using recursive =3D void_fol=
d_tuple_<I+1, N>;<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 recursive::call(action, tup)=
;<br>
=C2=A0=C2=A0 }<br>
};<br>
<br>
template <size_t N><br>
struct void_fold_tuple_<N, N> {<br>
=C2=A0=C2=A0 template <typename Action, typename Tuple&g=
t;<br>
=C2=A0=C2=A0 static void call(Action&, Tuple&) { /*=
no-op
*/ }<br>
};<br>
<br>
struct print_action {<br>
=C2=A0=C2=A0 template <typename Tuple, size_t I><br>
=C2=A0=C2=A0 void operator()(Tuple &tup) {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 using std::get; // ADL<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::cout << std::get&=
lt;I>(tup) <<
" ";<br>
=C2=A0=C2=A0 }<br>
};<br>
<br>
template <typename Action, typename Tuple><br>
void void_fold_tuple(Action &&action, Tuple
&&tup)<br>
{<br>
=C2=A0=C2=A0 using std::tuple_size; // ADL<br>
=C2=A0=C2=A0 using tuple =3D typename
std::remove_reference<Tuple>::type;<br>
=C2=A0=C2=A0 using recursive =3D void_fold_tuple_<0,
tuple_size<tuple>::value>;<br>
=C2=A0=C2=A0 recursive::call(action, tup);<br>
}<br>
<br>
int main() {<br>
=C2=A0=C2=A0 std::tuple<int, double, char const *>
tup{1,3.14,"hi",std::endl};<br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 0, 102);"><code class=3D"prettyprint"><code
class=3D"prettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(102, 0, 102);">=C2=A0=C2=A0
void_fold_tuple(print_action{}, tup);<br>
</span></code></code>};<br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"></span></div>
</code></div>
<br>
If something like the #N syntax were available then it would
simplify back to something that resembles strongly the first
case:<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(102, 0, 102);"></span><code
class=3D"prettyprint"><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 0, 102);">template <typename
Action, template <typename ...> class Tuple,
typename ...FTs><br>
void void_fold_tuple(Action &&action,
Tuple<FTs...> &&tup)<br>
{<br>
=C2=A0=C2=A0 auto x =3D {void_fold_one(action,
std::get<#FTs>(tup)...)};<br>
=C2=A0=C2=A0 (void) x;<br>
}<br>
<br>
int main() {<br>
=C2=A0=C2=A0 std::tuple<int, double, char const *> =
tup{1,
3.14, "hi", std::endl};<br>
=C2=A0=C2=A0 void_fold_tuple(print_action{}, tup);<br>
};</span></code></div>
</code></div>
<br>
Example 3<br>
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br>
<br>
Suppose we want to initialize the contents of a std::tuple using
a std::vector (this actually arose in our code when we have
templated child classes that specialize a virtual base class
used elsewhere). Right now the only way to achieve it is
something like the following:<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(102, 0, 102);">template<int...><b=
r>
struct Sequence { };<br>
<br>
template<size_t N, </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0,
102);"><code class=3D"prettyprint"><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0=
,
102);">size_t</span></code>... S><br>
struct GenSequence {<br>
=C2=A0=C2=A0 using type =3D typename GenSequence<N-1, N-=
1,
S...>::type;<br>
};<br>
<br>
template<</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 0, 102);"><code
class=3D"prettyprint"><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 0, 102);">size_t</span></code>=
....
S><br>
struct GenSequence<0, S...><br>
{<br>
=C2=A0=C2=A0 using type =3D Sequence<S...>;<br>
};<br>
<br>
template <typename... Ts><br>
struct Foo {<br>
=C2=A0=C2=A0 using Tuple =3D </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0,
102);"><code class=3D"prettyprint"><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0=
,
102);">std::tuple<Ts* ...>;<br>
=C2=A0=C2=A0 using Vector =3D std::vector<void*>;=
<br>
</span></code> =C2=A0=C2=A0 using Seq =3D typename
GenSequence<sizeof...(Ts)>::type;<br>
<br>
=C2=A0=C2=A0 Foo(Vector const &v) {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 init_pointers(v, Seq());<br>
=C2=A0=C2=A0 }<br>
<br>
=C2=A0=C2=A0 template <size_t ... S><br>
=C2=A0=C2=A0 void init_pointers(Vector const &v, Seq) {=
<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 _pointers =3D
Tuple{dynamic_cast<Ts*>(v[S])...};<br>
=C2=A0=C2=A0 }<br>
<br>
=C2=A0=C2=A0 Tuple _pointers;<br>
};<br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"></span></div>
</code></div>
<br>
With the new syntax that would simplify to:<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><code class=3D"prettyprint"><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0,
102);">template <typename... Ts><br>
struct Foo {<br>
=C2=A0=C2=A0 using Tuple =3D </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0,
102);"><code class=3D"prettyprint"><span
class=3D"styled-by-prettify" style=3D"color: rgb(102,
0, 102);">std::tuple<Ts* ...>;<br>
=C2=A0=C2=A0 using Vector =3D std::vector<void*>=
;;<br>
</span></code><br>
=C2=A0=C2=A0 Foo(Vector const &v) <br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 : _pointers{dynamic_cast&l=
t;Ts*>(v[#Ts])...}<br>
=C2=A0=C2=A0 {<br>
=C2=A0=C2=A0 }<br>
<br>
=C2=A0=C2=A0 Tuple _pointers;<br>
};<br>
</span></code><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);"></span></div>
</code></div>
<br>
Example 4<br>
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D<br>
<br>
Suppose I wanted to define a function that reverses the fields
of a tuple. With the proposed syntax it would not be difficult
to write such a function:<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(102, 0, 102);">template <size_t M,
typename T, typename... Ts><br>
struct Select{<br>
=C2=A0=C2=A0=C2=A0 using type =3D typename Select<M - 1,
Ts...>::type;<br>
};<br>
<br>
template <typename T, typename... Ts><br>
struct Select<0, T, Ts...>{<br>
=C2=A0=C2=A0=C2=A0 using type =3D T;<br>
};<br>
<br>
template <template <typename...> class Tuple,
typename... Ts><br>
auto reverse(Tuple<Ts...> const &tup) {<br>
=C2=A0=C2=A0 static constexpr size_t const N =3D </span><sp=
an
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0,
102);"><code class=3D"prettyprint"><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0=
,
102);"><code class=3D"prettyprint"><span
class=3D"styled-by-prettify" style=3D"color:
rgb(102, 0, 102);">sizeof...(Ts) - 1;</span></code>=
</span></code><br>
=C2=A0=C2=A0 using RTuple =3D </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0,
102);"><code class=3D"prettyprint"><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 0=
,
102);">Tuple<typename Select<N - #Ts,
Ts...>::type...>;<br>
=C2=A0</span></code>=C2=A0 return
RTuple<{std::get<N-#Ts>(tup)...};<br>
}<br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"></span></div>
</code></div>
<br>
I'll leave the vanilla C++14 version of the above function as an
exercise for the reader...<br>
<br>
Thoughts?<br>
Ryan Johnson</div>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to a topic in
the Google Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a moz-do-not-send=3D"true"
href=3D"https://groups.google.com/a/isocpp.org/d/topic/std-proposals/u9XLfR=
CKzGc/unsubscribe">https://groups.google.com/a/isocpp.org/d/topic/std-propo=
sals/u9XLfRCKzGc/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email
to <a moz-do-not-send=3D"true"
href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+=
unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a moz-do-not-send=3D"true"
href=3D"mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</=
a>.<br>
Visit this group at <a moz-do-not-send=3D"true"
href=3D"http://groups.google.com/a/isocpp.org/group/std-proposals/"=
>http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br>
</blockquote>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------080501060401080605050404--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Wed, 22 Jul 2015 07:52:41 -0600
Raw View
This is a multi-part message in MIME format.
--------------090603070909070602080807
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 22/07/2015 2:14 AM, David Krauss wrote:
> How about a special alias template, like this:
>
> template< typename type, std::size_t index >
> using indexed_type =3D type; // Compiler magic deduces index, too
>
> template <typename ... Ts, std::size_t ... Xs>
> std::vector<std::size_t> foo( std::indexed_type< Ts, Xs=20
> > && ...) { return {Xs...}; }
>
> An alias template can produce a deduced context as its result. Rather=20
> than introducing a new operator syntax for pack indexes, the library=20
> can encapsulate the =E2=80=9Coperator.=E2=80=9D The standard only needs t=
o say that=20
> index arguments are a deduced context when indexed_type is used in a=20
> pack pattern.
Compiler magic can be a good thing... and the committee seems to favor=20
it as well, with all those C++11 type traits being a prime example.
If I understand correctly, perhaps this might be another way of stating=20
your idea?
template <typename T, size_t N=3D/*magic*/>
struct indexof {
using type =3D T; /* for completeness */
static constexpr size_t value =3D N;
};
I'm not sure I follow how foo in your example would be used, tho? That=20
code would probably not compile, at least not if you invoked:
foo(1, 3.14, "hi")
Type deduction machinery generally fails if the types in the function's=20
argument list are derived somehow from---rather than directly=20
using---the types in the functions template parameter list.
The variant below compiles and runs with a normal C++11 compiler, though=20
lacking compiler magic it prints "0 0 0" instead of "0 1 2":
template <typename T, size_t N=3D0>
struct indexof {
using type =3D T; /* for completeness */
static constexpr size_t value =3D N;
};
template <typename... T>
std::vector<size_t> foo(T && ...args) {
return {std::indexof<T>::value...};
}
Versus a new keyword like __indexof, which operates in an unevaluated=20
context like alignof() and sizeof(), a magic std::indexof template has=20
the definite advantages of not polluting the global namespace. A slight=20
advantage is that std::indexof could degrade gracefully to value=3D0 when=
=20
passed a normal (non-pack) template parameter where __indexof would fail=20
to compile---though I'm not sure that's important, given the intended use.
std::indexof has the disadvantage of requiring significantly more typing=20
(though I'll admit it's impeccably C++-flavored boilerplate). A slight=20
disadvantage is that std::indexof would not provide the analogue to=20
__indexof(args) because it can only accept template packs [1].
Perhaps others could weigh in on which set of trade-offs is more desirable?
[1] I was shocked to discover that my prototype implementation of=20
__indexof in clang actually handles __indexof(T) and __indexof(args)=20
equally well, though I'd not considered the latter use case when I=20
implemented it. It will make a good addition to the unit tests.
Thoughts?
Ryan
>
> --=20
>
> ---
> You received this message because you are subscribed to a topic in the=20
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit=20
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/u9XLfRCKzGc/=
unsubscribe.
> To unsubscribe from this group and all its topics, send an email to=20
> std-proposals+unsubscribe@isocpp.org=20
> <mailto:std-proposals+unsubscribe@isocpp.org>.
> To post to this group, send email to std-proposals@isocpp.org=20
> <mailto:std-proposals@isocpp.org>.
> Visit this group at=20
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------090603070909070602080807
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 22/07/2015 2:14 AM, David Krauss
wrote:<br>
</div>
<blockquote
cite=3D"mid:5723B21C-0B63-432E-9BE1-F9DB7BE13574@gmail.com"
type=3D"cite">How about a special alias template, like this:
<div class=3D""><br class=3D"">
</div>
<div class=3D""><font class=3D"" face=3D"Courier">template< typena=
me
type, std::size_t index ></font></div>
<div class=3D""><font class=3D"" face=3D"Courier">using indexed_type =
=3D
type; // Compiler magic deduces index, too</font></div>
<div class=3D""><font class=3D"" face=3D"Courier"><br class=3D"">
</font></div>
<div class=3D""><font class=3D"" face=3D"Courier">template=C2=A0<t=
ypename=C2=A0...=C2=A0Ts,
std::size_t ... Xs><br class=3D"">
std::vector<std::size_t>=C2=A0foo( std::indexed_type<=C2=
=A0Ts,
Xs >=C2=A0&&=C2=A0...)=C2=A0{=C2=A0return=C2=A0{Xs...}=
; }<br class=3D"">
</font><br class=3D"">
</div>
<div class=3D"">An alias template can produce a deduced context as
its result. Rather than introducing a new operator syntax for
pack indexes, the library can encapsulate the =E2=80=9Coperator.=E2=
=80=9D The
standard only needs to say that <font class=3D"" face=3D"Courier">i=
ndex</font>
arguments are a deduced context when <font class=3D""
face=3D"Courier">indexed_type</font> is used in a pack pattern.</=
div>
</blockquote>
Compiler magic can be a good thing... and the committee seems to
favor it as well, with all those C++11 type traits being a prime
example. <br>
<br>
If I understand correctly, perhaps this might be another way of
stating your idea?<br>
<pre>template <typename T, size_t N=3D/*magic*/>
struct indexof {
using type =3D T; /* for completeness */
=C2=A0=C2=A0 static constexpr size_t value =3D N;
};</pre>
I'm not sure I follow how foo in your example would be used, tho?
That code would probably not compile, at least not if you invoked:<br>
<pre>foo(1, 3.14, "hi")</pre>
Type deduction machinery generally fails if the types in the
function's argument list are derived somehow from---rather than
directly using---the types in the functions template parameter list.
<br>
<br>
The variant below compiles and runs with a normal C++11 compiler,
though lacking compiler magic it prints "0 0 0" instead of "0 1 2":<br>
<pre>template <typename T, size_t N=3D0>
struct indexof {
using type =3D T; /* for completeness */
static constexpr size_t value =3D N;
};
template <typename... T>
std::vector<size_t> foo(T && ...args) {
return {std::indexof<T>::value...};
}
</pre>
Versus a new keyword like __indexof, which operates in an
unevaluated context like alignof() and sizeof(), a magic
std::indexof template has the definite advantages of not polluting
the global namespace. A slight advantage is that std::indexof could
degrade gracefully to value=3D0 when passed a normal (non-pack)
template parameter where __indexof would fail to compile---though
I'm not sure that's important, given the intended use. <br>
<br>
std::indexof has the disadvantage of requiring significantly more
typing (though I'll admit it's impeccably C++-flavored boilerplate).
A slight disadvantage is that std::indexof would not provide the
analogue to __indexof(args) because it can only accept template
packs [1].<br>
<br>
Perhaps others could weigh in on which set of trade-offs is more
desirable? <br>
<br>
[1] I was shocked to discover that my prototype implementation of
__indexof in clang actually handles __indexof(T) and __indexof(args)
equally well, though I'd not considered the latter use case when I
implemented it. It will make a good addition to the unit tests. <br>
<br>
Thoughts?<br>
Ryan<br>
<br>
<blockquote
cite=3D"mid:5723B21C-0B63-432E-9BE1-F9DB7BE13574@gmail.com"
type=3D"cite">
<div class=3D""><br class=3D"">
</div>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to a topic in
the Google Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a moz-do-not-send=3D"true"
href=3D"https://groups.google.com/a/isocpp.org/d/topic/std-proposals/u9XLfR=
CKzGc/unsubscribe">https://groups.google.com/a/isocpp.org/d/topic/std-propo=
sals/u9XLfRCKzGc/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email
to <a moz-do-not-send=3D"true"
href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposals+=
unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a moz-do-not-send=3D"true"
href=3D"mailto:std-proposals@isocpp.org">std-proposals@isocpp.org</=
a>.<br>
Visit this group at <a moz-do-not-send=3D"true"
href=3D"http://groups.google.com/a/isocpp.org/group/std-proposals/"=
>http://groups.google.com/a/isocpp.org/group/std-proposals/</a>.<br>
</blockquote>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------090603070909070602080807--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Wed, 22 Jul 2015 17:39:02 -0600
Raw View
This is a multi-part message in MIME format.
--------------070904030904010104010908
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 22/07/2015 2:14 AM, David Krauss wrote:
> How about a special alias template, like this:
>
> template< typename type, std::size_t index >
> using indexed_type =3D type; // Compiler magic deduces index, too
>
> template <typename ... Ts, std::size_t ... Xs>
> std::vector<std::size_t> foo( std::indexed_type< Ts, Xs=20
> > && ...) { return {Xs...}; }
>
> An alias template can produce a deduced context as its result. Rather=20
> than introducing a new operator syntax for pack indexes, the library=20
> can encapsulate the =E2=80=9Coperator.=E2=80=9D The standard only needs t=
o say that=20
> index arguments are a deduced context when indexed_type is used in a=20
> pack pattern.
On Wednesday, July 22, 2015 at 7:52:48 AM UTC-6, Ryan Johnson wrote:
On 22/07/2015 2:14 AM, David Krauss wrote:
> How about a special alias template, like this:
>
> template< typename type, std::size_t index >
> using indexed_type =3D type; // Compiler magic deduces index, too
>
> template <typename ... Ts, std::size_t ... Xs>
> std::vector<std::size_t> foo( std::indexed_type< Ts, Xs
> > && ...) { return {Xs...}; }
>
> An alias template can produce a deduced context as its result.
> Rather than introducing a new operator syntax for pack indexes,
> the library can encapsulate the =E2=80=9Coperator.=E2=80=9D The stand=
ard only
> needs to say that index arguments are a deduced context when
> indexed_type is used in a pack pattern.
Compiler magic can be a good thing... and the committee seems to
favor it as well, with all those C++11 type traits being a prime
example.
If I understand correctly, perhaps this might be another way of
stating your idea?
template <typename T, size_t N=3D/*magic*/>
struct indexof {
using type =3D T; /* for completeness */
static constexpr size_t value =3D N;
};
Hmm. After spending a bit of time trying to update my prototype to=20
support a std::indexof<T> approach, a couple of problems emerged:
1. Most "compiler magic" templates are actually normal templates whose
definition happens to wrap up built-in functions. For example, in
clang, you could define a simplified version of
std::is_trivially_destructible as:
|
template<typenameT>
structis_trivially_destructible {
staticconstexprboolvalue =3D__is_trivially_destructible(T);
};
|
Unfortunately, the obvious analogue for std::indexof<T> would be:
|
template<typenameT,size_t N=3D__indexof(T)>
structindexof {
staticconstexprsize_t value =3DN;
};
|
Without special treatment, that use of __indexof(T) will almost
certainly be evaluated at the wrong time and so fail to detect that
T is part of a parameter pack; the result would be either a
compilation error or a hard-wired N=3D0. I don't know yet how
difficult it would be to arrange for that special treatment. The
alternative would be to make the actual template name std::indexof
special and have the compiler propagate that special-ness across
using, typedef, etc. I don't think clang has any machinery in place
for that, though, so it would probably not be a fun change to make.
2. More worrisome, the std::indexof<T> approach cannot support non-type
template parameters: once you have this:
|
template<typenameT,size_t N=3D__indexof(T)>structindexof;
|
It is an error to define these:
|
template<int...T,size_t N=3D__indexof(T)>structindexof;
template<template<typename...>classT,size_t
N=3D__indexof(T)>structindexof;
|
Thus, you'd need three different names for the std::indexof<T>
concept, one for each kind of parameter pack, which would be pretty
annoying. The __indexof() built-in faces no such difficulty.
Thoughts?
Ryan
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------070904030904010104010908
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 22/07/2015 2:14 AM, David Krauss
wrote:<br>
</div>
<blockquote
cite=3D"mid:5723B21C-0B63-432E-9BE1-F9DB7BE13574@gmail.com"
type=3D"cite">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8">
<div class=3D"">How about a special alias template, like this:</div>
<div class=3D""><br class=3D"">
</div>
<div class=3D""><font class=3D"" face=3D"Courier">template< typena=
me
type, std::size_t index ></font></div>
<div class=3D""><font class=3D"" face=3D"Courier">using indexed_type =
=3D
type; // Compiler magic deduces index, too</font></div>
<div class=3D""><font class=3D"" face=3D"Courier"><br class=3D"">
</font></div>
<div class=3D""><font class=3D"" face=3D"Courier">template=C2=A0<t=
ypename=C2=A0...=C2=A0Ts,
std::size_t ... Xs><br class=3D"">
std::vector<std::size_t>=C2=A0foo( std::indexed_type<=C2=
=A0Ts,
Xs >=C2=A0&&=C2=A0...)=C2=A0{=C2=A0return=C2=A0{Xs...}=
; }<br class=3D"">
</font><br class=3D"">
</div>
<div class=3D"">An alias template can produce a deduced context as
its result. Rather than introducing a new operator syntax for
pack indexes, the library can encapsulate the =E2=80=9Coperator.=E2=
=80=9D The
standard only needs to say that <font class=3D"" face=3D"Courier">i=
ndex</font>
arguments are a deduced context when <font class=3D""
face=3D"Courier">indexed_type</font> is used in a pack pattern.</=
div>
</blockquote>
<br>
<br>
On Wednesday, July 22, 2015 at 7:52:48 AM UTC-6, Ryan Johnson wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex;
padding-left: 1ex; border-left-color: rgb(204, 204, 204);
border-left-width: 1px; border-left-style: solid;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>On 22/07/2015 2:14 AM, David Krauss wrote:<br>
</div>
<blockquote type=3D"cite">How about a special alias template, like
this:
<div><br>
</div>
<div><font face=3D"Courier">template< typename type,
std::size_t index ></font></div>
<div><font face=3D"Courier">using indexed_type =3D type; //
Compiler magic deduces index, too</font></div>
<div><font face=3D"Courier"><br>
</font></div>
<div><font face=3D"Courier">template=C2=A0<typename=C2=A0...=
=C2=A0Ts,
std::size_t ... Xs><br>
std::vector<std::size_t>=C2=A0foo(
std::indexed_type<=C2=A0Ts, Xs
>=C2=A0&&=C2=A0...)=C2=A0{=C2=A0return=C2=A0{Xs...=
}; }<br>
</font><br>
</div>
<div>An alias template can produce a deduced context as its
result. Rather than introducing a new operator syntax for
pack indexes, the library can encapsulate the =E2=80=9Coperator=
..=E2=80=9D
The standard only needs to say that <font face=3D"Courier">inde=
x</font>
arguments are a deduced context when <font face=3D"Courier">ind=
exed_type</font>
is used in a pack pattern.</div>
</blockquote>
Compiler magic can be a good thing... and the committee seems to
favor it as well, with all those C++11 type traits being a prime
example. <br>
<br>
If I understand correctly, perhaps this might be another way of
stating your idea?<br>
<pre>template <typename T, size_t N=3D/*magic*/>
struct indexof {
using type =3D T; /* for completeness */
=C2=A0=C2=A0 static constexpr size_t value =3D N;
};</pre>
</div>
</blockquote>
<div><br>
</div>
<div>Hmm. After spending a bit of time trying to update my prototype
to support a std::indexof<T> approach, a couple of problems
emerged:</div>
<div><br>
</div>
<ol>
<li>Most "compiler magic" templates are actually normal templates
whose definition happens to wrap up built-in functions. For
example, in clang, you could define a simplified version of
std::is_trivially_destructible as:<br>
<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); -ms-word-wrap: break-word; background-color: rgb(250,
250, 250);"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"><</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">typename</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><font color=3D"#222222"><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">struct</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">
is_trivially_destructible </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">{</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span></font><font color=3D"#222222"><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);">=C2=A0 =C2=A0</span><span class=3D"styled-by-prettif=
y"
style=3D"color: rgb(0, 0, 136);">static</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"> </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">constexpr</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"> </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">bool</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"> value </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">=3D</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"> __is_trivially_destructible</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">);</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span></font><font color=3D"#222222"><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">};</span></font><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span></div>
</code></div>
<br>
Unfortunately, the obvious analogue for std::indexof<T>
would be:<br>
<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); -ms-word-wrap: break-word; background-color: rgb(250,
250, 250);"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"><</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">typename</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">,</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> size_t N</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">=3D</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">__indexof</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">)></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><font color=3D"#222222"><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">struct</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> indexof </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">{</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span></font><font color=3D"#222222"><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);">=C2=A0 =C2=A0</span></font><span class=3D"styled-by-=
prettify"
style=3D"color: rgb(0, 0, 136);">static</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">constexpr</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
size_t value </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">=3D</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
N</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">;</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">};</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
><br>
</span></div>
</code></div>
<br>
Without special treatment, that use of __indexof(T) will almost
certainly be evaluated at the wrong time and so fail to detect
that T is part of a parameter pack; the result would be either a
compilation error or a hard-wired N=3D0. I don't know yet how
difficult it would be to arrange for that special treatment. The
alternative would be to make the actual template name
std::indexof special and have the compiler propagate that
special-ness across using, typedef, etc. I don't think clang has
any machinery in place for that, though, so it would probably
not be a fun change to make.<br>
<br>
</li>
<li>More worrisome, the std::indexof<T> approach cannot
support non-type template parameters: once you have this:<br>
<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); -ms-word-wrap: break-word; background-color: rgb(250,
250, 250);"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"><</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">typename</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">,</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> size_t N</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">=3D</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">__indexof</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">)></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">struct</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> indexof</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">;</span></div>
</code></div>
<br>
It is an error to define these:<br>
<br>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); -ms-word-wrap: break-word; background-color: rgb(250,
250, 250);"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
"
style=3D"color: rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"><</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">int</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">...</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
T</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">,</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
size_t N</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">=3D</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>__indexof</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">)></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">struct</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> indexof</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">;</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"><</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">template</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);"><</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">typename</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">...></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">class</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">,</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> size_t N</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">=3D</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">__indexof</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">)></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">struct</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> indexof</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">;</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span></div>
</code></div>
<br>
Thus, you'd need three different names for the
std::indexof<T> concept, one for each kind of parameter
pack, which would be pretty annoying. The __indexof() built-in
faces no such difficulty. <br>
<br>
</li>
</ol>
<p>Thoughts?<br>
Ryan<br>
<br>
</p>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------070904030904010104010908--
.
Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Wed, 22 Jul 2015 23:48:54 -0700 (PDT)
Raw View
------=_Part_180_1898468478.1437634134223
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Why not make indexof a magic variable template? Then you don't need the ::v=
alue at the point of use and you don't need three different versions. You s=
till face the implementation issue of not being able to use the pattern of =
a normal template calling a magic function though.
return { std::indexof<Ts>... };
And this magically works whether Ts is a pack of types, values or templates=
..
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_180_1898468478.1437634134223--
.
Author: David Krauss <potswa@gmail.com>
Date: Thu, 23 Jul 2015 14:52:50 +0800
Raw View
--Apple-Mail=_3A7ED410-9923-43E6-BCED-4F7C46C86B85
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9307=E2=80=9323, at 7:39 AM, Ryan Johnson <scovich@gmail.co=
m> wrote:
>=20
> Unfortunately, the obvious analogue for std::indexof<T> would be:
>=20
> template <typename T, size_t N=3D__indexof(T)>
> struct indexof {
> static constexpr size_t value =3D N;
> };
That=E2=80=99s why I suggested an alias template. Alias template substituti=
ons occur before argument substitutions or type deduction. So, the usage
template <typename ... Ts, std::size_t ... Xs>
std::vector<std::size_t> foo( std::indexed_type< Ts, Xs > && ...) { return =
{Xs...}; }
gets transformed into something like
template <typename ... Ts, std::size_t ... Xs>
std::vector<std::size_t> foo( Ts [[__index (Xs)]] && ...) { return {Xs...};=
}
What I=E2=80=99m trying to illustrate here is that the parameter type will =
be Ts && regardless of the Xs values, but Xs can still be deduced from the =
context where the alias template was used, because the alias template has b=
een substituted away before deduction begins.
This is a completely different animal from type traits.
> More worrisome, the std::indexof<T> approach cannot support non-type temp=
late parameters:
The alias template adds a different restriction: there needs to be a sequen=
ce of deduced types in the function signature or partial specialization tem=
plate-id. The main pack can be non-type.
> Thus, you'd need three different names for the std::indexof<T> concept, o=
ne for each kind of parameter pack, which would be pretty annoying. The __i=
ndexof() built-in faces no such difficulty.=20
Maybe Clang can implement __indexof() without difficulty, but an operator t=
hat equally accepts a template name, type, or expression as an argument doe=
sn=E2=80=99t fit into the language grammar (and might not fit into other im=
plementations) as easily.
Personally, I consider non-type template parameters as second-class citizen=
s and keep them quarantined in the smallest possible utility classes. Unfor=
tunately, not everyone feels this way, and the workarounds are inconvenient=
to impossible.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_3A7ED410-9923-43E6-BCED-4F7C46C86B85
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9307=
=E2=80=9323, at 7:39 AM, Ryan Johnson <<a href=3D"mailto:scovich@gmail.c=
om" class=3D"">scovich@gmail.com</a>> wrote:</div><div class=3D""><div b=
gcolor=3D"#FFFFFF" text=3D"#000000" class=3D""><ol class=3D""><li class=3D"=
"><br class=3D"">
Unfortunately, the obvious analogue for std::indexof<T>
would be:<br class=3D"">
<br class=3D"">
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); -ms-word-wrap: break-word; background-color: rgb(250,
250, 250);"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><span class=3D"styled-by-prettify=
" style=3D"color: rgb(0, 0, 136);">template</span><span class=3D"styled-by-=
prettify" style=3D"">
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"><</span><span class=3D"styled-by-pret=
tify" style=3D"color: rgb(0, 0,
136);">typename</span><span class=3D"styled-by-prettify" st=
yle=3D""> T</span><span class=3D"styled-by-prettify" style=3D"color: rgb(10=
2, 102,
0);">,</span><span class=3D"styled-by-prettify" style=3D"">=
size_t N</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102,=
102,
0);">=3D</span><span class=3D"styled-by-prettify" style=3D"=
">__indexof</span><span class=3D"styled-by-prettify" style=3D"color: rgb(10=
2, 102,
0);">(</span><span class=3D"styled-by-prettify" style=3D"">=
T</span><span class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">)></span><span class=3D"styled-by-prettify" style=
=3D""><br class=3D"">
</span><font color=3D"#222222" class=3D""><span class=3D"styl=
ed-by-prettify" style=3D"color: rgb(0, 0,
136);">struct</span><span class=3D"styled-by-prettify" st=
yle=3D""> indexof </span><span class=3D"styled-by-prettify" style=3D"color:=
rgb(102, 102,
0);">{</span><span class=3D"styled-by-prettify" style=3D"=
"><br class=3D"">
</span></font><font color=3D"#222222" class=3D""><span clas=
s=3D"styled-by-prettify" style=3D""> </span></font><span class=
=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 136);">static</span><span=
class=3D"styled-by-prettify" style=3D"">
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">constexpr</span><span class=3D"styled-by-p=
rettify" style=3D"">
size_t value </span><span class=3D"styled-by-prettify" styl=
e=3D"color: rgb(102, 102, 0);">=3D</span><span class=3D"styled-by-prettify"=
style=3D"">
N</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">;</span><span class=3D"styled-by-prettif=
y" style=3D""><br class=3D"">
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">};</span><span class=3D"styled-by-pretti=
fy" style=3D""><br class=3D"">
</span></div>
</code></div>
</li></ol></div></div></blockquote><div><br class=3D""></div><div>T=
hat=E2=80=99s why I suggested an alias template. Alias template substitutio=
ns occur before argument substitutions or type deduction. So, the usage</di=
v><div><br class=3D""></div><font face=3D"Courier" class=3D"">template <=
typename ... Ts, std::size_t ... Xs><br class=3D"">std::vector<std::s=
ize_t> foo( std::indexed_type< Ts, Xs > && ...) { return {=
Xs...}; }</font></div><div><br class=3D""></div><div>gets transformed into =
something like</div><div><br class=3D""></div><div><div><font face=3D"Couri=
er" class=3D"">template <typename ... Ts, std::size_t ... Xs><br clas=
s=3D"">std::vector<std::size_t> foo( Ts [[__index (Xs)]] && .=
...) { return {Xs...}; }</font></div><div><font face=3D"Courier" class=3D"">=
<br class=3D""></font></div><div>What I=E2=80=99m trying to illustrate here=
is that the parameter type will be <font face=3D"Courier" class=3D"">Ts &a=
mp;&</font> regardless of the <font face=3D"Courier" class=3D"">Xs</fon=
t> values, but <span style=3D"font-family: Courier;" class=3D"">Xs</sp=
an> can still be deduced from the context where the alias template was=
used, because the alias template has been substituted away before deductio=
n begins.</div><div><br class=3D""></div><div>This is a completely differen=
t animal from type traits.</div><div><br class=3D""></div><blockquote type=
=3D"cite" class=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#0000=
00" class=3D""><ol class=3D"" start=3D"1">
<li class=3D"">More worrisome, the std::indexof<T> approach can=
not
support non-type template parameters: </li></ol></div></div></block=
quote><div>The alias template adds a different restriction: there needs to =
be a sequence of deduced types in the function signature or partial special=
ization template-id. The main pack can be non-type.</div><blockquote type=
=3D"cite" class=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#0000=
00" class=3D""><ol class=3D"" start=3D"2"><li class=3D"">Thus, you'd need t=
hree different names for the
std::indexof<T> concept, one for each kind of parameter
pack, which would be pretty annoying. The __indexof() built-in
faces no such difficulty. <br class=3D""></li></ol></div></div></bl=
ockquote></div><div>Maybe Clang can implement <font face=3D"Courier" class=
=3D"">__indexof()</font> without difficulty, but an operator that equally a=
ccepts a template name, type, or expression as an argument doesn=E2=80=99t =
fit into the language grammar (and might not fit into other implementations=
) as easily.</div><br class=3D""><div class=3D"">Personally, I consider non=
-type template parameters as second-class citizens and keep them quarantine=
d in the smallest possible utility classes. Unfortunately, not everyone fee=
ls this way, and the workarounds are inconvenient to impossible.</div><div =
class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_3A7ED410-9923-43E6-BCED-4F7C46C86B85--
.
Author: Giovanni Piero Deretta <gpderetta@gmail.com>
Date: Thu, 23 Jul 2015 02:25:07 -0700 (PDT)
Raw View
------=_Part_363_992006095.1437643507937
Content-Type: multipart/alternative;
boundary="----=_Part_364_1963272000.1437643507937"
------=_Part_364_1963272000.1437643507937
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Thursday, July 23, 2015 at 7:53:00 AM UTC+1, David Krauss wrote:
>
>
>
> [...]
>
>
> 1. Thus, you'd need three different names for the std::indexof<T>=20
> concept, one for each kind of parameter pack, which would be pretty=20
> annoying. The __indexof() built-in faces no such difficulty.=20
> =20
> Maybe Clang can implement __indexof() without difficulty, but an operator=
=20
> that equally accepts a template name, type, or expression as an argument=
=20
> doesn=E2=80=99t fit into the language grammar (and might not fit into oth=
er=20
> implementations) as easily.
>
don't know about template name, but sizeof has accepted either type or an=
=20
expression without issues since forever. Also new operators have been added=
=20
recently (decltype, alignas, noexcept), without the need to wrap them in a=
=20
metafunction veneer. Ryan should just propose the __indexof operator as=20
implemented and leave the non-clashing-name bikeshedding to the committee.=
=20
-- gpd
=20
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_364_1963272000.1437643507937
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, July 23, 2015 at 7:53:00 AM UTC+1, David Krau=
ss wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wr=
ap:break-word"><br><div><br></div><div>[...]<br><blockquote type=3D"cite"><=
div><div bgcolor=3D"#FFFFFF" text=3D"#000000"><ol start=3D"2"><li>Thus, you=
'd need three different names for the
std::indexof<T> concept, one for each kind of parameter
pack, which would be pretty annoying. The __indexof() built-in
faces no such difficulty. <br></li></ol></div></div></blockquote></=
div><div>Maybe Clang can implement <font face=3D"Courier">__indexof()</font=
> without difficulty, but an operator that equally accepts a template name,=
type, or expression as an argument doesn=E2=80=99t fit into the language g=
rammar (and might not fit into other implementations) as easily.</div></div=
></blockquote><div><br>don't know about template name, but sizeof has a=
ccepted either type or an expression without issues since forever. Also new=
operators have been added recently (decltype, alignas, noexcept), without =
the need to wrap them in a metafunction veneer. Ryan should just propose th=
e __indexof operator as implemented and leave the non-clashing-name bikeshe=
dding to the committee. <br><br>-- gpd<br>=C2=A0</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_364_1963272000.1437643507937--
------=_Part_363_992006095.1437643507937--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Thu, 23 Jul 2015 05:59:05 -0600
Raw View
This is a multi-part message in MIME format.
--------------070909060405090202000202
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 23/07/2015 12:52 AM, David Krauss wrote:
>
>> On 2015=E2=80=9307=E2=80=9323, at 7:39 AM, Ryan Johnson <scovich@gmail.c=
om=20
>> <mailto:scovich@gmail.com>> wrote:
>>
>> 1.
>>
>>
>> Unfortunately, the obvious analogue for std::indexof<T> would be:
>>
>> |
>> template<typenameT,size_t N=3D__indexof(T)>
>> structindexof {
>> staticconstexprsize_t value =3DN;
>> };
>> |
>>
>
> That=E2=80=99s why I suggested an alias template. Alias template substitu=
tions=20
> occur before argument substitutions or type deduction. So, the usage
>
> template <typename ... Ts, std::size_t ... Xs>
> std::vector<std::size_t> foo( std::indexed_type< Ts, Xs > && ...) {=20
> return {Xs...}; }
>
> gets transformed into something like
>
> template <typename ... Ts, std::size_t ... Xs>
> std::vector<std::size_t> foo( Ts [[__index (Xs)]] && ...) { return=20
> {Xs...}; }
>
> What I=E2=80=99m trying to illustrate here is that the parameter type wil=
l be=20
> Ts && regardless of the Xs values, but Xs can still be deduced from=20
> the context where the alias template was used, because the alias=20
> template has been substituted away before deduction begins.
OK, I read that too quickly before and didn't "get" that=20
std::indexed_type<Ts,Xs> *is* Ts.
However, the compiler won't know that, and I'm still struggling to see=20
how the code you propose could actually compile. I'm not aware of any=20
case where today's compilers can "work backward" from a function arg=20
whose type is both instantiation-dependent and type-dependent on T, and=20
successfully infer what T should be (unless T is also used directly).
Can you elaborate on that part?
Also, even if it can somehow be made to compile, that style of syntax is=20
very different from today's C++, which would worry me. The committee=20
seems to be less enthusiastic about proposals that require novel new=20
syntax in order to work.
>> 2. Thus, you'd need three different names for the std::indexof<T>
>> concept, one for each kind of parameter pack, which would be
>> pretty annoying. The __indexof() built-in faces no such difficulty.
>>
> ...
>
> Personally, I consider non-type template parameters as second-class=20
> citizens and keep them quarantined in the smallest possible utility=20
> classes.
Actually, that's a good point, and the whole point of this proposal is=20
drastically reduce the need for `template <typename... Ts> template=20
<sizeof_t... Ns>' nesting that's often required for working with=20
std::tuple. Template template parameters are handy in the cases where=20
they're useful---I think template <template <typename...> class Tuple,=20
typename... Ts> is the official way to work with tuple-like objects, for=20
example---but those are definitely less common than type parameters.
Anyway, I guess the world would not end if there were a std::indexof for=20
typed, std::indexofN for non-type, and std::indexofT for template=20
template or some such. Still ugly, though.
Thoughts?
Ryan
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------070909060405090202000202
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 23/07/2015 12:52 AM, David Krauss
wrote:<br>
</div>
<blockquote
cite=3D"mid:2919925F-0AD4-4829-91FB-72979643229A@gmail.com"
type=3D"cite">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8">
<br class=3D"">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">On 2015=E2=80=9307=E2=80=9323, at 7:39 AM, Ryan J=
ohnson <<a
moz-do-not-send=3D"true" href=3D"mailto:scovich@gmail.com"
class=3D"">scovich@gmail.com</a>> wrote:</div>
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<ol class=3D"">
<li class=3D""><br class=3D"">
Unfortunately, the obvious analogue for
std::indexof<T> would be:<br class=3D"">
<br class=3D"">
<div class=3D"prettyprint" style=3D"border: 1px solid
rgb(187, 187, 187); -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span
class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D""> </span><=
span
class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"><</span><span
class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">typename</span><span
class=3D"styled-by-prettify" style=3D""> T</span>=
<span
class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">,</span><span
class=3D"styled-by-prettify" style=3D""> size_t N=
</span><span
class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">=3D</span><span
class=3D"styled-by-prettify" style=3D"">__indexof=
</span><span
class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">(</span><span
class=3D"styled-by-prettify" style=3D"">T</span><=
span
class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">)></span><span
class=3D"styled-by-prettify" style=3D""><br
class=3D"">
</span><font class=3D"" color=3D"#222222"><span
class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">struct</span><span
class=3D"styled-by-prettify" style=3D""> indexo=
f
</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">{</span><spa=
n
class=3D"styled-by-prettify" style=3D""><br
class=3D"">
</span></font><font class=3D"" color=3D"#222222">=
<span
class=3D"styled-by-prettify" style=3D"">=C2=A0 =
=C2=A0</span></font><span
class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">static</span><span
class=3D"styled-by-prettify" style=3D""> </span><=
span
class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">constexpr</span><span
class=3D"styled-by-prettify" style=3D""> size_t
value </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">=3D</span><spa=
n
class=3D"styled-by-prettify" style=3D""> N</span>=
<span
class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">;</span><span
class=3D"styled-by-prettify" style=3D""><br
class=3D"">
</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">};</span><span
class=3D"styled-by-prettify" style=3D""><br
class=3D"">
</span></div>
</code></div>
</li>
</ol>
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>That=E2=80=99s why I suggested an alias template. Alias templa=
te
substitutions occur before argument substitutions or type
deduction. So, the usage</div>
<div><br class=3D"">
</div>
<font class=3D"" face=3D"Courier">template <typename ... Ts,
std::size_t ... Xs><br class=3D"">
std::vector<std::size_t> foo( std::indexed_type< Ts,
Xs > && ...) { return {Xs...}; }</font></div>
<div><br class=3D"">
</div>
<div>gets transformed into something like</div>
<div><br class=3D"">
</div>
<div>
<div><font class=3D"" face=3D"Courier">template <typename ... Ts=
,
std::size_t ... Xs><br class=3D"">
std::vector<std::size_t> foo( Ts [[__index (Xs)]]
&& ...) { return {Xs...}; }</font></div>
<div><font class=3D"" face=3D"Courier"><br class=3D"">
</font></div>
<div>What I=E2=80=99m trying to illustrate here is that the paramet=
er
type will be <font class=3D"" face=3D"Courier">Ts &&</fon=
t>
regardless of the <font class=3D"" face=3D"Courier">Xs</font>
values, but=C2=A0<span style=3D"font-family: Courier;" class=3D""=
>Xs</span>=C2=A0can
still be deduced from the context where the alias template was
used, because the alias template has been substituted away
before deduction begins.</div>
</div>
</blockquote>
OK, I read that too quickly before and didn't "get" that
std::indexed_type<Ts,Xs> *is* Ts. <br>
<br>
However, the compiler won't know that, and I'm still struggling to
see how the code you propose could actually compile. I'm not aware
of any case where today's compilers can "work backward" from a
function arg whose type is both instantiation-dependent and
type-dependent on T, and successfully infer what T should be (unless
T is also used directly). <br>
<br>
Can you elaborate on that part? <br>
<br>
Also, even if it can somehow be made to compile, that style of
syntax is very different from today's C++, which would worry me. The
committee seems to be less enthusiastic about proposals that require
novel new syntax in order to work.<br>
<br>
<blockquote
cite=3D"mid:2919925F-0AD4-4829-91FB-72979643229A@gmail.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<ol class=3D"" start=3D"2">
<li class=3D"">Thus, you'd need three different names for
the std::indexof<T> concept, one for each kind
of parameter pack, which would be pretty annoying. The
__indexof() built-in faces no such difficulty. <br
class=3D"">
</li>
</ol>
</div>
</div>
</blockquote>
</div>
<div>...</div>
<br class=3D"">
<div class=3D"">Personally, I consider non-type template parameters
as second-class citizens and keep them quarantined in the
smallest possible utility classes.</div>
</blockquote>
Actually, that's a good point, and the whole point of this proposal
is drastically reduce the need for `template <typename... Ts>
template <sizeof_t... Ns>' nesting that's often required for
working with std::tuple. Template template parameters are handy in
the cases where they're useful---I think template <template
<typename...> class Tuple, typename... Ts> is the official
way to work with tuple-like objects, for example---but those are
definitely less common than type parameters. <br>
<br>
Anyway, I guess the world would not end if there were a std::indexof
for typed, std::indexofN for non-type, and std::indexofT for
template template or some such. Still ugly, though. <br>
<br>
Thoughts?<br>
Ryan<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------070909060405090202000202--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Thu, 23 Jul 2015 06:10:42 -0600
Raw View
This is a multi-part message in MIME format.
--------------060104040701000106050208
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 23/07/2015 12:48 AM, Bengt Gustafsson wrote:
> Why not make indexof a magic variable template? Then you don't need the :=
:value at the point of use and you don't need three different versions. You=
still face the implementation issue of not being able to use the pattern o=
f a normal template calling a magic function though.
>
> return { std::indexof<Ts>... };
>
> And this magically works whether Ts is a pack of types, values or templat=
es.
>
Good point. If this ends up going the template route rather than the=20
new-keyword route, variable templates would definitely be the way to go.
Still not sure about giving a particular template name special treatment=20
by the compiler, tho... tracing its heritage across various aliases=20
would require non-trivial work, and argument dependent lookup would be a=20
mess. For example:
|
template<typenameT>
usingmy_indexof =3Dstd::indexof<T>;// why not?
template<size_t N>
usingint_indexof =3Dstd::indexof<N>;// eh???
namespacefoo {template<typenameT>size_t indexof =3D/* something */;}
namespacebar {template<intN>size_t indexof =3D/* something */;}
usingstd::indexof;
usingfoo::indexof;
usingbar::indexof;
/* what now? */
|
I'm sure it could all be worked through, but it would all be new, prone=20
to causing unintended consequences, and feels orthogonal to this=20
proposal. The additional complexity and feature creep would worry me.
Ryan
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------060104040701000106050208
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 23/07/2015 12:48 AM, Bengt
Gustafsson wrote:<br>
</div>
<blockquote
cite=3D"mid:683797ce-9eff-4bc4-85ba-563131e9b4d9@isocpp.org"
type=3D"cite">
<pre wrap=3D"">Why not make indexof a magic variable template? Then y=
ou don't need the ::value at the point of use and you don't need three diff=
erent versions. You still face the implementation issue of not being able t=
o use the pattern of a normal template calling a magic function though.
return { std::indexof<Ts>... };
And this magically works whether Ts is a pack of types, values or templates=
..
</pre>
</blockquote>
Good point. If this ends up going the template route rather than the
new-keyword route, variable templates would definitely be the way to
go. <br>
<br>
Still not sure about giving a particular template name special
treatment by the compiler, tho... tracing its heritage across
various aliases would require non-trivial work, and argument
dependent lookup would be a mess. For example:<br>
<br>
<div>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><font color=3D"#000000"><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">template</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);"><</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">typename</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
T</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">></span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">using</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
my_indexof </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">=3D</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
std</span><span class=3D"styled-by-prettify" style=3D"color=
:
rgb(102, 102, 0);">::</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>indexof</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);"><</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">>;</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(136, 0,
0);">// why not?</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);"><</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>size_t
N</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">></span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
><br>
</span><font color=3D"#666600"><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">using</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> int_indexof </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">=3D</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> std</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">::</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">indexof</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);"><</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">N</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">>;</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(136, 0,
0);">// eh???</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">namespace</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"> foo </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">{</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"> </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"> </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);"><</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">typename</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> size_t indexof </span><sp=
an
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">=3D</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(136, 0,
0);">/* something */</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">;</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">}</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">namespace</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"> bar </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">{</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"> </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">template</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"> </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);"><</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">int</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> N</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> size_t indexof </span><sp=
an
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">=3D</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(136, 0,
0);">/* something */</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">;</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102=
,
0);">}</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
<br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">using</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"> std</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">::</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);">indexof</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">;</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">using</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"> foo</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">::</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);">indexof</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">;</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">using</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"> bar</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">::</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);">indexof</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">;</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(136, 0, 0);">/* what now? */</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
0);"><br>
</span></font></font></div>
</code></div>
</div>
<div><br>
</div>
I'm sure it could all be worked through, but it would all be new,
prone to causing unintended consequences, and feels orthogonal to
this proposal. The additional complexity and feature creep would
worry me. <br>
<br>
Ryan<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------060104040701000106050208--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Thu, 23 Jul 2015 06:23:35 -0600
Raw View
This is a multi-part message in MIME format.
--------------050909090802080805030505
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 23/07/2015 3:25 AM, Giovanni Piero Deretta wrote:
> On Thursday, July 23, 2015 at 7:53:00 AM UTC+1, David Krauss wrote:
>
>
>
> [...]
>>
>> 2. Thus, you'd need three different names for the
>> std::indexof<T> concept, one for each kind of parameter pack,
>> which would be pretty annoying. The __indexof() built-in
>> faces no such difficulty.
>>
> Maybe Clang can implement __indexof() without difficulty, but an
> operator that equally accepts a template name, type, or expression
> as an argument doesn=E2=80=99t fit into the language grammar (and mig=
ht
> not fit into other implementations) as easily.
>
>
> don't know about template name, but sizeof has accepted either type or=20
> an expression without issues since forever.
Exactly. I was able to implement __indexof() in just a few hours by=20
copy-pasting Clang's code for sizeof...(). No reason to expect a=20
drastically different situation in other compilers.
> Also new operators have been added recently (decltype, alignas,=20
> noexcept), without the need to wrap them in a metafunction veneer.=20
> Ryan should just propose the __indexof operator as implemented and=20
> leave the non-clashing-name bikeshedding to the committee.
What I'm hoping I can do, just to give the proposal maximum traction, is=20
propose the magic __indexof() function and make a convincing argument=20
that it can be implemented in a way that admits a metafunction veneer,=20
should the committee decide to go that route.
The hope is that something like this (borrowing from Bengt's idea) would=20
be to let __indexof(T) accept non-pack arguments (defaulting to value=20
0), and then have this definition:
|
template<typenameT,size_t N=3D__indexof(T)>
constexprsize_t constindexof =3DN;
|
Because N is instantiation-dependent on T, __indexof(T) cannot take a=20
value at template declaration time. The hope, then, is that code like this:
|
template<typename...Ts>
structindexes {
staticconstexprsize_t values[]=3D{std::indexof<Ts>...};
};
|
Would substitute the parameter pack into std::indexof before pack=20
expansion begins (which seems likely), at which point the magic I've=20
already implemented could kick in during pack expansion as usual. So far=20
my clang-foo has not been up to the task of hooking into template=20
parameter substitution process, though, because I'm not aware of any=20
similar operator whose implementation I can use for inspiration.
Thanks,
Ryan
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------050909090802080805030505
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 23/07/2015 3:25 AM, Giovanni Piero
Deretta wrote:<br>
</div>
<blockquote
cite=3D"mid:34faf735-0eb9-40a9-ab94-cd512bf69502@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">On Thursday, July 23, 2015 at 7:53:00 AM UTC+1,
David Krauss wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div style=3D"word-wrap:break-word"><br>
<div><br>
</div>
<div>[...]<br>
<blockquote type=3D"cite">
<div>
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<ol start=3D"2">
<li>Thus, you'd need three different names for the
std::indexof<T> concept, one for each kind
of parameter pack, which would be pretty
annoying. The __indexof() built-in faces no such
difficulty. <br>
</li>
</ol>
</div>
</div>
</blockquote>
</div>
<div>Maybe Clang can implement <font face=3D"Courier">__indexof=
()</font>
without difficulty, but an operator that equally accepts a
template name, type, or expression as an argument doesn=E2=80=
=99t
fit into the language grammar (and might not fit into
other implementations) as easily.</div>
</div>
</blockquote>
<div><br>
don't know about template name, but sizeof has accepted either
type or an expression without issues since forever. </div>
</div>
</blockquote>
Exactly. I was able to implement __indexof() in just a few hours by
copy-pasting Clang's code for sizeof...(). No reason to expect a
drastically different situation in other compilers.<br>
<br>
<blockquote
cite=3D"mid:34faf735-0eb9-40a9-ab94-cd512bf69502@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div>Also new operators have been added recently (decltype,
alignas, noexcept), without the need to wrap them in a
metafunction veneer. Ryan should just propose the __indexof
operator as implemented and leave the non-clashing-name
bikeshedding to the committee. <br>
</div>
</div>
</blockquote>
What I'm hoping I can do, just to give the proposal maximum
traction, is propose the magic __indexof() function and make a
convincing argument that it can be implemented in a way that admits
a metafunction veneer, should the committee decide to go that route.
<br>
<br>
The hope is that something like this (borrowing from Bengt's idea)
would be to let __indexof(T) accept non-pack arguments (defaulting
to value 0), and then have this definition:<br>
<div>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><font color=3D"#000088"><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">template</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);"><</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">typename</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
T</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">,</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
size_t N</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">=3D</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>__indexof</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">(</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">)></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">constexpr</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
size_t </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">const</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 0);">indexof </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">=3D</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> N</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">;</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span></font></div>
</code></div>
</div>
<br>
Because N is instantiation-dependent on T, __indexof(T) cannot take
a value at template declaration time. The hope, then, is that code
like this:<br>
<div>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); border-image: none; -ms-word-wrap: break-word;
background-color: rgb(250, 250, 250);"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><font color=3D"#000088"><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0,
136);">template</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> </span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);"><</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 136);">typename</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">...</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"> T</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">s></span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">struct</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
indexes </span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">{</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
><br>
=C2=A0 =C2=A0</span><span class=3D"styled-by-prettify" styl=
e=3D"color:
rgb(0, 0, 136);">static</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(0, 0, 136);">constexpr</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
size_t values</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(102, 102, 0);">[]</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">=3D</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">{</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(0, 0, 0);"=
>std</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">::</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">indexof</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);"><</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);">Ts</span><span
class=3D"styled-by-prettify" style=3D"color: rgb(102, 102,
0);">>...};</span><span class=3D"styled-by-prettify"
style=3D"color: rgb(0, 0, 0);"><br>
</span><span class=3D"styled-by-prettify" style=3D"color:
rgb(102, 102, 0);">};</span></font></div>
</code></div>
</div>
<br>
Would substitute the parameter pack into std::indexof before pack
expansion begins (which seems likely), at which point the magic I've
already implemented could kick in during pack expansion as usual. So
far my clang-foo has not been up to the task of hooking into
template parameter substitution process, though, because I'm not
aware of any similar operator whose implementation I can use for
inspiration. <br>
<br>
Thanks,<br>
Ryan<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------050909090802080805030505--
.
Author: David Krauss <potswa@mac.com>
Date: Thu, 23 Jul 2015 20:48:47 +0800
Raw View
--Apple-Mail=_58BB2AA1-7CB7-4F5F-9B8A-61FC1FBE356E
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9307=E2=80=9323, at 7:59 PM, Ryan Johnson <scovich@gmail.co=
m> wrote:
>=20
> On 23/07/2015 12:52 AM, David Krauss wrote:
>>=20
>> That=E2=80=99s why I suggested an alias template. Alias template substit=
utions occur before argument substitutions or type deduction. So, the usage
>>=20
>> template <typename ... Ts, std::size_t ... Xs>
>> std::vector<std::size_t> foo( std::indexed_type< Ts, Xs > && ...) { retu=
rn {Xs...}; }
>>=20
>> gets transformed into something like
>>=20
>> template <typename ... Ts, std::size_t ... Xs>
>> std::vector<std::size_t> foo( Ts [[__index (Xs)]] && ...) { return {Xs..=
..}; }
>>=20
>> What I=E2=80=99m trying to illustrate here is that the parameter type wi=
ll be Ts && regardless of the Xs values, but Xs can still be deduced from t=
he context where the alias template was used, because the alias template ha=
s been substituted away before deduction begins.
> OK, I read that too quickly before and didn't "get" that std::indexed_typ=
e<Ts,Xs> *is* Ts.=20
>=20
> However, the compiler won't know that, and I'm still struggling to see ho=
w the code you propose could actually compile. I'm not aware of any case wh=
ere today's compilers can "work backward" from a function arg whose type is=
both instantiation-dependent and type-dependent on T, and successfully inf=
er what T should be (unless T is also used directly).=20
Since C++11, this will compile:
template< typename t >
using same_type =3D t;
template< typename t >
t id( same_type< t > value ) { return value; }
int q =3D id( 3 );
same_type is an alias template, hence it is substituted before deduction. T=
here=E2=80=99s no working backward.
My suggestion is to add a hidden deduced context, e.g. in an internal attri=
bute. That=E2=80=99s what the compiler would know about.
> Also, even if it can somehow be made to compile, that style of syntax is =
very different from today's C++, which would worry me. The committee seems =
to be less enthusiastic about proposals that require novel new syntax in or=
der to work.
It=E2=80=99s nothing new: mention a template parameter in a deduced context=
, and its value is determined.
> Actually, that's a good point, and the whole point of this proposal is dr=
astically reduce the need for `template <typename... Ts> template <sizeof_t=
.... Ns>' nesting that's often required for working with std::tuple.
Can you cite some code with this symptom? The problem doesn=E2=80=99t look =
familiar to me.
> Template template parameters are handy in the cases where they're useful-=
--I think template <template <typename...> class Tuple, typename... Ts> is =
the official way to work with tuple-like objects, for example---but those a=
re definitely less common than type parameters.=20
Template template parameters are less powerful than a conventional =E2=80=
=9Cconcept=E2=80=9D of classes with a member template named temp. I tend to=
prefer the latter. Except, of course, when it=E2=80=99s a parameter of a p=
artial specialization and the purpose is introspection.
Tuple-like objects are not guaranteed to have the form template< typename .=
... > class Tuple. In fact std::array is already an exception to that rule. =
Templates work by duck typing, and unless it=E2=80=99s part of the class in=
terface that template arguments can be unpacked and inspected, that operati=
on is off-limits. (That=E2=80=99s a terrible style of interface definition =
=E2=80=94 that=E2=80=99s why classes have members.)
> Anyway, I guess the world would not end if there were a std::indexof for =
typed, std::indexofN for non-type, and std::indexofT for template template =
or some such. Still ugly, though.=20
At some point, you start to rationalize dropping the std:: and making it a =
first-class operator. I think the most intuitive behavior, if operators are=
allowed, is to have something that expands to an index sequence pack of a =
given length =E2=80=94 no enclosing pack pattern needed.
template <typename...Ts>
std::vector<size_t> foo(Ts&& ...) {
constexpr std::size_t pack_length =3D sizeof ... (Ts);
return { index_sequence( pack_length ) ... };
}
This would allow users to generate expressions from patterns without introd=
ucing templates at all.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_58BB2AA1-7CB7-4F5F-9B8A-61FC1FBE356E
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9307=
=E2=80=9323, at 7:59 PM, Ryan Johnson <<a href=3D"mailto:scovich@gmail.c=
om" class=3D"">scovich@gmail.com</a>> wrote:</div><br class=3D"Apple-int=
erchange-newline"><div class=3D"">
=20
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
" class=3D"">
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<div class=3D"moz-cite-prefix">On 23/07/2015 12:52 AM, David Krauss
wrote:<br class=3D"">
</div>
<blockquote cite=3D"mid:2919925F-0AD4-4829-91FB-72979643229A@gmail.com"=
type=3D"cite" class=3D"">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8" class=3D"">
<br class=3D"">
<div class=3D"">
<div class=3D"">That=E2=80=99s why I suggested an alias template. A=
lias template
substitutions occur before argument substitutions or type
deduction. So, the usage</div>
<div class=3D""><br class=3D"">
</div>
<font class=3D"" face=3D"Courier">template <typename ... Ts,
std::size_t ... Xs><br class=3D"">
std::vector<std::size_t> foo( std::indexed_type< Ts,
Xs > && ...) { return {Xs...}; }</font></div>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">gets transformed into something like</div>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">
<div class=3D""><font class=3D"" face=3D"Courier">template <type=
name ... Ts,
std::size_t ... Xs><br class=3D"">
std::vector<std::size_t> foo( Ts [[__index (Xs)]]
&& ...) { return {Xs...}; }</font></div>
<div class=3D""><font class=3D"" face=3D"Courier"><br class=3D"">
</font></div>
<div class=3D"">What I=E2=80=99m trying to illustrate here is that =
the parameter
type will be <font class=3D"" face=3D"Courier">Ts &&</fon=
t>
regardless of the <font class=3D"" face=3D"Courier">Xs</font>
values, but <span style=3D"font-family: Courier;" class=3D""=
>Xs</span> can
still be deduced from the context where the alias template was
used, because the alias template has been substituted away
before deduction begins.</div>
</div>
</blockquote>
OK, I read that too quickly before and didn't "get" that
std::indexed_type<Ts,Xs> *is* Ts. <br class=3D"">
<br class=3D"">
However, the compiler won't know that, and I'm still struggling to
see how the code you propose could actually compile. I'm not aware
of any case where today's compilers can "work backward" from a
function arg whose type is both instantiation-dependent and
type-dependent on T, and successfully infer what T should be (unless
T is also used directly). <br class=3D""></div></div></blockquote><div>=
<br class=3D""></div><div>Since C++11, this will compile:</div><div><br cla=
ss=3D""></div><div><font face=3D"Courier" class=3D"">template< typename =
t ></font></div><div><font face=3D"Courier" class=3D"">using same_type =
=3D t;</font></div><div><font face=3D"Courier" class=3D""><br class=3D""></=
font></div><div><font face=3D"Courier" class=3D"">template< typename t &=
gt;</font></div><div><font face=3D"Courier" class=3D"">t id( same_type< =
t > value ) { return value; }</font></div><div><font face=3D"Courier" cl=
ass=3D""><br class=3D""></font></div><div><font face=3D"Courier" class=3D""=
>int q =3D id( 3 );</font></div><div><br class=3D""></div><div><font face=
=3D"Courier" class=3D"">same_type</font> is an alias template, hence it is =
substituted before deduction. There=E2=80=99s no working backward.</div><di=
v><br class=3D""></div><div>My suggestion is to add a hidden deduced contex=
t, e.g. in an internal attribute. That=E2=80=99s what the compiler would kn=
ow about.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div cla=
ss=3D""><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">Also, even if =
it can somehow be made to compile, that style of
syntax is very different from today's C++, which would worry me. The
committee seems to be less enthusiastic about proposals that require
novel new syntax in order to work.<br class=3D""></div></div></blockquo=
te><div><br class=3D""></div><div>It=E2=80=99s nothing new: mention a templ=
ate parameter in a deduced context, and its value is determined.</div><br c=
lass=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div bgcolor=
=3D"#FFFFFF" text=3D"#000000" class=3D"">Actually, that's a good point, and=
the whole point of this proposal
is drastically reduce the need for `template <typename... Ts>
template <sizeof_t... Ns>' nesting that's often required for
working with std::tuple. </div></div></blockquote><div><br class=3D""><=
/div><div>Can you cite some code with this symptom? The problem doesn=E2=80=
=99t look familiar to me.</div><br class=3D""><blockquote type=3D"cite" cla=
ss=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"=
">Template template parameters are handy in
the cases where they're useful---I think template <template
<typename...> class Tuple, typename... Ts> is the official
way to work with tuple-like objects, for example---but those are
definitely less common than type parameters. <br class=3D""></div></div=
></blockquote><div><br class=3D""></div><div>Template template parameters a=
re less powerful than a conventional =E2=80=9Cconcept=E2=80=9D of classes w=
ith a member template named <font face=3D"Courier" class=3D"">temp</font>. =
I tend to prefer the latter. Except, of course, when it=E2=80=99s a paramet=
er of a partial specialization and the purpose is introspection.</div><div>=
<br class=3D""></div><div>Tuple-like objects are not guaranteed to have the=
form <font face=3D"Courier" class=3D"">template< typename ... > clas=
s Tuple</font>. In fact <font face=3D"Courier" class=3D"">std::array</font>=
is already an exception to that rule. Templates work by duck typing, and u=
nless it=E2=80=99s part of the class interface that template arguments can =
be unpacked and inspected, that operation is off-limits. (That=E2=80=99s a =
terrible style of interface definition =E2=80=94 that=E2=80=99s why classes=
have members.)</div><br class=3D""><blockquote type=3D"cite" class=3D""><d=
iv class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">Anyway, =
I guess the world would not end if there were a std::indexof
for typed, std::indexofN for non-type, and std::indexofT for
template template or some such. Still ugly, though. <br class=3D""></di=
v></div></blockquote><br class=3D""></div><div>At some point, you start to =
rationalize dropping the <font face=3D"Courier" class=3D"">std::</font> and=
making it a first-class operator. I think the most intuitive behavior, if =
operators are allowed, is to have something that expands to an index sequen=
ce pack of a given length =E2=80=94 no enclosing pack pattern needed.</div>=
<div><br class=3D""></div><div><font face=3D"Courier" class=3D"">template&n=
bsp;<typename...Ts><br class=3D"">std::vector<size_t> foo(=
Ts&& ...) {</font></div><div><font face=3D"Courier" class=3D""=
> constexpr std::size_t pack_length =3D </font><span styl=
e=3D"font-family: Courier;" class=3D"">sizeof ... (Ts);</span></div><div><f=
ont face=3D"Courier" class=3D""> return { index_sequence(=
</font><span style=3D"font-family: Courier;" class=3D"">pack_length</=
span><span style=3D"font-family: Courier;" class=3D""> ) </span><=
span style=3D"font-family: Courier;" class=3D"">... };</span></div><div><sp=
an style=3D"font-family: Courier;" class=3D"">}</span></div><div><br class=
=3D""></div><div>This would allow users to generate expressions from patter=
ns without introducing templates at all.</div><div><br class=3D""></div></b=
ody></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_58BB2AA1-7CB7-4F5F-9B8A-61FC1FBE356E--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Thu, 23 Jul 2015 07:27:27 -0600
Raw View
This is a multi-part message in MIME format.
--------------090909010309090704010209
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 23/07/2015 6:48 AM, David Krauss wrote:
>
>> On 2015=E2=80=9307=E2=80=9323, at 7:59 PM, Ryan Johnson <scovich@gmail.c=
om=20
>> <mailto:scovich@gmail.com>> wrote:
>>
>> On 23/07/2015 12:52 AM, David Krauss wrote:
>>>
>>> That=E2=80=99s why I suggested an alias template. Alias template=20
>>> substitutions occur before argument substitutions or type deduction.=20
>>> So, the usage
>>>
>>> template <typename ... Ts, std::size_t ... Xs>
>>> std::vector<std::size_t> foo( std::indexed_type< Ts, Xs > && ...) {=20
>>> return {Xs...}; }
>>>
>>> gets transformed into something like
>>>
>>> template <typename ... Ts, std::size_t ... Xs>
>>> std::vector<std::size_t> foo( Ts [[__index (Xs)]] && ...) { return=20
>>> {Xs...}; }
>>>
>>> What I=E2=80=99m trying to illustrate here is that the parameter type w=
ill=20
>>> be Ts && regardless of the Xs values, but Xs can still be deduced=20
>>> from the context where the alias template was used, because the=20
>>> alias template has been substituted away before deduction begins.
>> OK, I read that too quickly before and didn't "get" that=20
>> std::indexed_type<Ts,Xs> *is* Ts.
>>
>> However, the compiler won't know that, and I'm still struggling to=20
>> see how the code you propose could actually compile. I'm not aware of=20
>> any case where today's compilers can "work backward" from a function=20
>> arg whose type is both instantiation-dependent and type-dependent on=20
>> T, and successfully infer what T should be (unless T is also used=20
>> directly).
>
> Since C++11, this will compile:
>
> template< typename t >
> using same_type =3D t;
>
> template< typename t >
> t id( same_type< t > value ) { return value; }
>
> int q =3D id( 3 );
>
> same_type is an alias template, hence it is substituted before=20
> deduction. There=E2=80=99s no working backward.
>
> My suggestion is to add a hidden deduced context, e.g. in an internal=20
> attribute. That=E2=80=99s what the compiler would know about.
The part that worries me is this code does not compile:
template <typename T, size_t N=3D0>
using indexed_type =3D T;
template <typename T, typename N>
size_t foo(indexed_type<T,N> &&) { return N; }
int main() { return foo("hi");}
Because the compiler cannot figure out how to come up with N while=20
instantiating foo. On gcc-4.9 for example:
scratch.cpp: In function =E2=80=98int main()=E2=80=99:
scratch.cpp:15:20: error: no matching function for call to =E2=80=98foo(con=
st=20
char [3])=E2=80=99
return foo("hi");
^
scratch.cpp:15:20: note: candidate is:
scratch.cpp:12:8: note: template<class T, long unsigned int N> size_t=20
foo(indexed_type<T, N>&&)
size_t foo(indexed_type<T, N> &&) { return N; }
^
scratch.cpp:12:8: note: template argument deduction/substitution failed:
scratch.cpp:15:20: note: couldn't deduce template parameter =E2=80=98N=E2=
=80=99
return foo("hi");
^
I fail to see how adding magic to indexed_type, so that N takes a=20
meaningful value, would get past the deduction failure that has already=20
occurred before the compiler ever tried to instantiate indexed_type.=20
Today's compiler can't work backwards from the magical N of indexed_type=20
in order to deduce the ordinary N of foo; type aliases do not change=20
that situation as far as I can tell---your example compiles because the=20
user has already supplied T and so alias substitution can go ahead; the=20
user has *not* supplied N and so the compiler is unable to continue.
That's the part I was hoping you could elaborate on.
>> Actually, that's a good point, and the whole point of this proposal=20
>> is drastically reduce the need for `template <typename... Ts>=20
>> template <sizeof_t... Ns>' nesting that's often required for working=20
>> with std::tuple.
>
> Can you cite some code with this symptom? The problem doesn=E2=80=99t loo=
k=20
> familiar to me.
The code examples I cited in my original message can all be cast to use=20
integer sequences instead of recursion; we chose to go with recursion=20
rather than a variadic template helper function that takes a=20
std::integer_sequence as an argument (following advice that variadic=20
templates are slow and should be avoided when possible).
The documentation for std::integer_sequence has some nice examples:
http://en.cppreference.com/w/cpp/utility/integer_sequence
Stack Overflow is crawling with questions on the theme of how to turn=20
<typename ...Ts> into <size_t ...Ns> when dealing with tuples. Here are=20
just a few that turned up when I searched for "c++11 index tuple"
http://stackoverflow.com/questions/28997271/c11-way-to-index-tuple-at-runti=
me-without-using-switch
http://stackoverflow.com/questions/27936332/c11-building-a-stdtuple-from-a-=
template-function
http://stackoverflow.com/questions/17854219/creating-a-sub-tuple-starting-f=
rom-a-stdtuplesome-type
As a concrete example, suppose you're writing a set of generic hash=20
functions:
template <typename T>
int hash(T const &t); // to be specialized/overridden
template <typename... Ts>
struct helper {
template <size_t... Ns>
static int hash(std::tuple<Ts...> const &tup,=20
std::integer_sequence<Ns...>)
{
return (... ^ hash(std::get<Ts>(tup)));
}
};
template <typename... Ts>
int hash(std::tuple<Ts...> const &tup) {
return helper<Ts...>::hash(tup, std::integer_sequence_for<Ts...>());
}
With __indexof() the body of the hash function for std::tuple reduces to:
return (... ^ hash(std::get<__indexof(Ts)>(tup)));
>> Anyway, I guess the world would not end if there were a std::indexof=20
>> for typed, std::indexofN for non-type, and std::indexofT for template=20
>> template or some such. Still ugly, though.
>
> At some point, you start to rationalize dropping the std:: and making=20
> it a first-class operator. I think the most intuitive behavior, if=20
> operators are allowed, is to have something that expands to an index=20
> sequence pack of a given length =E2=80=94 no enclosing pack pattern neede=
d.
>
> template <typename...Ts>
> std::vector<size_t> foo(Ts&& ...) {
> constexpr std::size_t pack_length =3D sizeof ... (Ts);
> return { index_sequence( pack_length ) ... };
> }
>
> This would allow users to generate expressions from patterns without=20
> introducing templates at all.
It would take someone smarter than me to figure out how to implement=20
that in a compiler. index_sequence takes a constant integer expression=20
and so there is no indication that it has anything to do with parameter=20
packs.
Seems like, if you're going to go this route, you'd want something like=20
the N3723 someone mentioned earlier in this thread. That's a vastly=20
bigger and more invasive feature than what I was proposing here, tho.=20
Plus, I get the sense that the two are orthogonal: you could still=20
benefit from an __indexof() as a simpler alternative to marshalling all=20
that parameter pack manipulation machinery N3723 proposes.
Thoughts?
Ryan
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------090909010309090704010209
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 23/07/2015 6:48 AM, David Krauss
wrote:<br>
</div>
<blockquote cite=3D"mid:A526687A-5EA3-4562-91C7-47EE886A1767@mac.com"
type=3D"cite">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8">
<br class=3D"">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">On 2015=E2=80=9307=E2=80=9323, at 7:59 PM, Ryan J=
ohnson <<a
moz-do-not-send=3D"true" href=3D"mailto:scovich@gmail.com"
class=3D"">scovich@gmail.com</a>> wrote:</div>
<br class=3D"Apple-interchange-newline">
<div class=3D"">
<meta content=3D"text/html; charset=3Dutf-8"
http-equiv=3D"Content-Type" class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<div class=3D"moz-cite-prefix">On 23/07/2015 12:52 AM, David
Krauss wrote:<br class=3D"">
</div>
<blockquote
cite=3D"mid:2919925F-0AD4-4829-91FB-72979643229A@gmail.com"
type=3D"cite" class=3D"">
<meta http-equiv=3D"Content-Type" content=3D"text/html;
charset=3Dutf-8" class=3D"">
<br class=3D"">
<div class=3D"">
<div class=3D"">That=E2=80=99s why I suggested an alias
template. Alias template substitutions occur before
argument substitutions or type deduction. So, the
usage</div>
<div class=3D""><br class=3D"">
</div>
<font class=3D"" face=3D"Courier">template <typename
... Ts, std::size_t ... Xs><br class=3D"">
std::vector<std::size_t> foo(
std::indexed_type< Ts, Xs > && ...) {
return {Xs...}; }</font></div>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">gets transformed into something like</div>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">
<div class=3D""><font class=3D"" face=3D"Courier">templat=
e
<typename ... Ts, std::size_t ... Xs><br
class=3D"">
std::vector<std::size_t> foo( Ts [[__index
(Xs)]] && ...) { return {Xs...}; }</font></di=
v>
<div class=3D""><font class=3D"" face=3D"Courier"><br
class=3D"">
</font></div>
<div class=3D"">What I=E2=80=99m trying to illustrate her=
e is
that the parameter type will be <font class=3D""
face=3D"Courier">Ts &&</font> regardless of
the <font class=3D"" face=3D"Courier">Xs</font> values,
but=C2=A0<span style=3D"font-family: Courier;" class=3D=
"">Xs</span>=C2=A0can
still be deduced from the context where the alias
template was used, because the alias template has
been substituted away before deduction begins.</div>
</div>
</blockquote>
OK, I read that too quickly before and didn't "get" that
std::indexed_type<Ts,Xs> *is* Ts. <br class=3D"">
<br class=3D"">
However, the compiler won't know that, and I'm still
struggling to see how the code you propose could actually
compile. I'm not aware of any case where today's compilers
can "work backward" from a function arg whose type is both
instantiation-dependent and type-dependent on T, and
successfully infer what T should be (unless T is also used
directly). <br class=3D"">
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>Since C++11, this will compile:</div>
<div><br class=3D"">
</div>
<div><font class=3D"" face=3D"Courier">template< typename t >=
</font></div>
<div><font class=3D"" face=3D"Courier">using same_type =3D t;</font=
></div>
<div><font class=3D"" face=3D"Courier"><br class=3D"">
</font></div>
<div><font class=3D"" face=3D"Courier">template< typename t >=
</font></div>
<div><font class=3D"" face=3D"Courier">t id( same_type< t >
value ) { return value; }</font></div>
<div><font class=3D"" face=3D"Courier"><br class=3D"">
</font></div>
<div><font class=3D"" face=3D"Courier">int q =3D id( 3 );</font></d=
iv>
<div><br class=3D"">
</div>
<div><font class=3D"" face=3D"Courier">same_type</font> is an alias
template, hence it is substituted before deduction. There=E2=80=
=99s no
working backward.</div>
<div><br class=3D"">
</div>
<div>My suggestion is to add a hidden deduced context, e.g. in
an internal attribute. That=E2=80=99s what the compiler would kno=
w
about.</div>
</div>
</blockquote>
The part that worries me is this code does not compile:<br>
<br>
<tt>template <typename T, size_t N=3D0></tt><tt><br>
</tt><tt>using indexed_type =3D T;</tt><tt><br>
</tt><tt><br>
</tt><tt>template <typename T, typename N></tt><tt><br>
</tt><tt>size_t foo(indexed_type<T,N> &&) { re</tt><tt>tu=
rn
N; }</tt><tt><br>
</tt><tt><br>
</tt><tt>int main() { return foo("hi");</tt><tt> }</tt><tt><br>
</tt><br>
Because the compiler cannot figure out how to come up with N while
instantiating foo. On gcc-4.9 for example:<br>
<br>
<tt>scratch.cpp: In function =E2=80=98int main()=E2=80=99:</tt><tt><br>
</tt><tt>
scratch.cpp:15:20: error: no matching function for call to
=E2=80=98foo(const char [3])=E2=80=99</tt><tt><br>
</tt><tt>
=C2=A0=C2=A0=C2=A0=C2=A0 return foo("hi");</tt><tt><br>
</tt><tt>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ^</tt><tt><br>
</tt><tt>
scratch.cpp:15:20: note: candidate is:</tt><tt><br>
</tt><tt>
scratch.cpp:12:8: note: template<class T, long unsigned int
N> size_t foo(indexed_type<T, N>&&)</tt><tt><br>
</tt><tt>
=C2=A0size_t foo(indexed_type<T, N> &&) { return N; }</=
tt><tt><br>
</tt><tt>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ^</tt><tt><br>
</tt><tt>
scratch.cpp:12:8: note:=C2=A0=C2=A0 template argument deduction/subst=
itution
failed:</tt><tt><br>
</tt><tt>
scratch.cpp:15:20: note:=C2=A0=C2=A0 couldn't deduce template paramet=
er =E2=80=98N=E2=80=99</tt><tt><br>
</tt><tt>
=C2=A0=C2=A0=C2=A0=C2=A0 return foo("hi");</tt><tt><br>
</tt><tt>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ^</tt><br>
<br>
I fail to see how adding magic to indexed_type, so that N takes a
meaningful value, would get past the deduction failure that has
already occurred before the compiler ever tried to instantiate
indexed_type. Today's compiler can't work backwards from the magical
N of indexed_type in order to deduce the ordinary N of foo; type
aliases do not change that situation as far as I can tell---your
example compiles because the user has already supplied T and so
alias substitution can go ahead; the user has *not* supplied N and
so the compiler is unable to continue.<br>
<br>
That's the part I was hoping you could elaborate on.<br>
<br class=3D"">
<blockquote cite=3D"mid:A526687A-5EA3-4562-91C7-47EE886A1767@mac.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">Actually,
that's a good point, and the whole point of this proposal
is drastically reduce the need for `template
<typename... Ts> template <sizeof_t... Ns>'
nesting that's often required for working with std::tuple.
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>Can you cite some code with this symptom? The problem
doesn=E2=80=99t look familiar to me.</div>
</div>
</blockquote>
The code examples I cited in my original message can all be cast to
use integer sequences instead of recursion; we chose to go with
recursion rather than a variadic template helper function that takes
a std::integer_sequence as an argument (following advice that
variadic templates are slow and should be avoided when possible). <br>
<br>
The documentation for std::integer_sequence has some nice examples:<br>
<a class=3D"moz-txt-link-freetext" href=3D"http://en.cppreference.com/w=
/cpp/utility/integer_sequence">http://en.cppreference.com/w/cpp/utility/int=
eger_sequence</a><br>
<br>
Stack Overflow is crawling with questions on the theme of how to
turn <typename ...Ts> into <size_t ...Ns> when dealing
with tuples. Here are just a few that turned up when I searched for
"c++11 index tuple"<br>
<br>
<a class=3D"moz-txt-link-freetext" href=3D"http://stackoverflow.com/questio=
ns/28997271/c11-way-to-index-tuple-at-runtime-without-using-switch">http://=
stackoverflow.com/questions/28997271/c11-way-to-index-tuple-at-runtime-with=
out-using-switch</a><br>
<a class=3D"moz-txt-link-freetext" href=3D"http://stackoverflow.com/questio=
ns/27936332/c11-building-a-stdtuple-from-a-template-function">http://stacko=
verflow.com/questions/27936332/c11-building-a-stdtuple-from-a-template-func=
tion</a><br>
<a class=3D"moz-txt-link-freetext" href=3D"http://stackoverflow.com/questio=
ns/17854219/creating-a-sub-tuple-starting-from-a-stdtuplesome-type">http://=
stackoverflow.com/questions/17854219/creating-a-sub-tuple-starting-from-a-s=
tdtuplesome-type</a><br>
<br>
As a concrete example, suppose you're writing a set of generic hash
functions:<br>
<br>
<tt>template <typename T></tt><tt><br>
</tt><tt>int hash(T const &t); // to be specialized/overridden</tt>=
<tt><br>
</tt><tt><br>
template <typename... Ts><br>
struct helper {<br>
=C2=A0=C2=A0 template <size_t... Ns><br>
=C2=A0=C2=A0 static int hash(std::tuple<Ts...> const &tup,
std::integer_sequence<Ns...>)<br>
=C2=A0=C2=A0 {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return (... ^ hash(std::get<Ts>(=
tup)));<br>
=C2=A0=C2=A0 }<br>
};<br>
<br>
</tt><tt>template <typename... Ts></tt><tt><br>
</tt><tt>int hash(std::tuple<Ts...> const &tup) {</tt><tt><br=
>
</tt><tt>=C2=A0=C2=A0 return helper<Ts...>::</tt><tt>hash(tup,
std::integer_sequence_for<Ts...>());<br>
</tt><tt>}</tt><br>
<br>
With __indexof() the body of the hash function for std::tuple
reduces to:<br>
<br>
<tt>return (... ^ hash(std::get<__indexof(Ts)>(tup)));</tt><br>
<br class=3D"">
<blockquote cite=3D"mid:A526687A-5EA3-4562-91C7-47EE886A1767@mac.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">Anyway, I
guess the world would not end if there were a std::indexof
for typed, std::indexofN for non-type, and std::indexofT
for template template or some such. Still ugly, though. <br
class=3D"">
</div>
</div>
</blockquote>
<br class=3D"">
</div>
<div>At some point, you start to rationalize dropping the <font
class=3D"" face=3D"Courier">std::</font> and making it a
first-class operator. I think the most intuitive behavior, if
operators are allowed, is to have something that expands to an
index sequence pack of a given length =E2=80=94 no enclosing pack
pattern needed.</div>
<div><br class=3D"">
</div>
<div><font class=3D"" face=3D"Courier">template=C2=A0<typename...T=
s><br
class=3D"">
std::vector<size_t>=C2=A0foo(Ts&&=C2=A0...) {</font=
></div>
<div><font class=3D"" face=3D"Courier">=C2=A0 =C2=A0 constexpr std::s=
ize_t
pack_length =3D=C2=A0</font><span style=3D"font-family: Courier;"
class=3D"">sizeof ... (Ts);</span></div>
<div><font class=3D"" face=3D"Courier">=C2=A0 =C2=A0 return=C2=A0{ in=
dex_sequence(=C2=A0</font><span
style=3D"font-family: Courier;" class=3D"">pack_length</span><spa=
n
style=3D"font-family: Courier;" class=3D"">=C2=A0)=C2=A0</span><s=
pan
style=3D"font-family: Courier;" class=3D"">... };</span></div>
<div><span style=3D"font-family: Courier;" class=3D"">}</span></div>
<div><br class=3D"">
</div>
<div>This would allow users to generate expressions from patterns
without introducing templates at all.</div>
</blockquote>
<br>
It would take someone smarter than me to figure out how to implement
that in a compiler. index_sequence takes a constant integer
expression and so there is no indication that it has anything to do
with parameter packs. <br>
<br>
Seems like, if you're going to go this route, you'd want something
like the N3723 someone mentioned earlier in this thread. That's a
vastly bigger and more invasive feature than what I was proposing
here, tho. Plus, I get the sense that the two are orthogonal: you
could still benefit from an __indexof() as a simpler alternative to
marshalling all that parameter pack manipulation machinery N3723
proposes.<br>
<br>
Thoughts?<br>
Ryan<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------090909010309090704010209--
.
Author: David Krauss <potswa@gmail.com>
Date: Fri, 24 Jul 2015 11:06:35 +0800
Raw View
--Apple-Mail=_03D04176-22BE-4281-AB3B-537A9C964DAB
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9307=E2=80=9323, at 9:27 PM, Ryan Johnson <scovich@gmail.co=
m> wrote:
>=20
> On 23/07/2015 6:48 AM, David Krauss wrote:
>>=20
>>> On 2015=E2=80=9307=E2=80=9323, at 7:59 PM, Ryan Johnson <scovich@gmail.=
com <mailto:scovich@gmail.com>> wrote:
>>>=20
>>> On 23/07/2015 12:52 AM, David Krauss wrote:
>>>>=20
>>>> That=E2=80=99s why I suggested an alias template. Alias template subst=
itutions occur before argument substitutions or type deduction. So, the usa=
ge
>>>>=20
>>>> template <typename ... Ts, std::size_t ... Xs>
>>>> std::vector<std::size_t> foo( std::indexed_type< Ts, Xs > && ...) { re=
turn {Xs...}; }
>>>>=20
>>>> gets transformed into something like
>>>>=20
>>>> template <typename ... Ts, std::size_t ... Xs>
>>>> std::vector<std::size_t> foo( Ts [[__index (Xs)]] && ...) { return {Xs=
....}; }
>>>>=20
>>>> What I=E2=80=99m trying to illustrate here is that the parameter type =
will be Ts && regardless of the Xs values, but Xs can still be deduced from=
the context where the alias template was used, because the alias template =
has been substituted away before deduction begins.
>>> OK, I read that too quickly before and didn't "get" that std::indexed_t=
ype<Ts,Xs> *is* Ts.=20
>>>=20
>>> However, the compiler won't know that, and I'm still struggling to see =
how the code you propose could actually compile. I'm not aware of any case =
where today's compilers can "work backward" from a function arg whose type =
is both instantiation-dependent and type-dependent on T, and successfully i=
nfer what T should be (unless T is also used directly).=20
>>=20
>> Since C++11, this will compile:
>>=20
>> template< typename t >
>> using same_type =3D t;
>>=20
>> template< typename t >
>> t id( same_type< t > value ) { return value; }
>>=20
>> int q =3D id( 3 );
>>=20
>> same_type is an alias template, hence it is substituted before deduction=
.. There=E2=80=99s no working backward.
>>=20
>> My suggestion is to add a hidden deduced context, e.g. in an internal at=
tribute. That=E2=80=99s what the compiler would know about.
> The part that worries me is this code does not compile:
>=20
> template <typename T, size_t N=3D0>
What=E2=80=99s the default argument for?
> using indexed_type =3D T;
>=20
> template <typename T, typename N>
> size_t foo(indexed_type<T,N> &&) { return N; }
>=20
> int main() { return foo("hi"); }
>=20
> Because the compiler cannot figure out how to come up with N while instan=
tiating foo. On gcc-4.9 for example:
Yes, that is the hidden magic. It=E2=80=99s not a pure library solution. It=
=E2=80=99s a library interface with no need to add new syntax.
(What were you expecting? There are no instructions for sequential counting=
in that program.)
> I fail to see how adding magic to indexed_type, so that N takes a meaning=
ful value, would get past the deduction failure that has already occurred b=
efore the compiler ever tried to instantiate indexed_type.
>=20
> Today's compiler can't work backwards from the magical N of indexed_type =
in order to deduce the ordinary N of foo; type aliases do not change that s=
ituation as far as I can tell---your example compiles because the user has =
already supplied T and so alias substitution can go ahead; the user has *no=
t* supplied N and so the compiler is unable to continue.
The user doesn=E2=80=99t supply N, deduction (the =E2=80=9Ccompiler magic=
=E2=80=9D) does. I illustrated it as an attribute:
template <typename ... Ts, std::size_t ... Xs>
std::vector<std::size_t> foo( Ts [[__index (Xs)]] && ...) { return {Xs...};=
}
__index(Xs) is the deduced context. The double brackets are unnecessary, se=
rving only for illustrative syntactic orientation. For comparison, consider=
this:
template< typename t, std::size_t v >
using ic =3D std::integral_constant< t, v >;
template <typename ... Ts, std::size_t ... Xs>
std::vector<std::size_t> foo( ic< Ts, Xs > ...) { return {Xs...}; }
int main() {
auto v =3D foo( std::integral_constant< std::size_t, 3 >{}, std::integr=
al_constant< std::size_t, 42 >{} );
}
This is valid C++11. The compiler doesn=E2=80=99t need the arguments of tem=
plate parameters in order to substitute them into an alias template. (Defau=
lt template arguments of alias templates don=E2=80=99t work the same way, s=
o you might get confused if you tend to add default arguments everywhere. I=
never suggested any default arguments.)
> That's the part I was hoping you could elaborate on.
>=20
>>> Actually, that's a good point, and the whole point of this proposal is =
drastically reduce the need for `template <typename... Ts> template <sizeof=
_t... Ns>' nesting that's often required for working with std::tuple.
>>=20
>> Can you cite some code with this symptom? The problem doesn=E2=80=99t lo=
ok familiar to me.
> The code examples I cited in my original message can all be cast to use i=
nteger sequences instead of recursion; we chose to go with recursion rather=
than a variadic template helper function that takes a std::integer_sequenc=
e as an argument (following advice that variadic templates are slow and sho=
uld be avoided when possible).=20
Huh? std::tuple_element is not slower than a recursive template that reinve=
nts it. Parameter packs are usually faster than recursive templates. Recurs=
ive templates are the C++98-era solution.
The GenSequence example makes it look like you were unaware of the existenc=
e of std::make_index_sequence.
> The documentation for std::integer_sequence has some nice examples:
> http://en.cppreference.com/w/cpp/utility/integer_sequence <http://en.cppr=
eference.com/w/cpp/utility/integer_sequence>
>=20
> Stack Overflow is crawling with questions on the theme of how to turn <ty=
pename ...Ts> into <size_t ...Ns> when dealing with tuples. Here are just a=
few that turned up when I searched for "c++11 index tuple=E2=80=9D
I see. So "`template <typename... Ts> template <sizeof_t... Ns>=E2=80=99 ne=
sting=E2=80=9D is referring to the practice of declaring a nested class tem=
plate, and then defining it out side the enclosing class definition. But wh=
y would someone write it that way?
> http://stackoverflow.com/questions/28997271/c11-way-to-index-tuple-at-run=
time-without-using-switch <http://stackoverflow.com/questions/28997271/c11-=
way-to-index-tuple-at-runtime-without-using-switch>
> http://stackoverflow.com/questions/27936332/c11-building-a-stdtuple-from-=
a-template-function <http://stackoverflow.com/questions/27936332/c11-buildi=
ng-a-stdtuple-from-a-template-function>
> http://stackoverflow.com/questions/17854219/creating-a-sub-tuple-starting=
-from-a-stdtuplesome-type <http://stackoverflow.com/questions/17854219/crea=
ting-a-sub-tuple-starting-from-a-stdtuplesome-type>
I don=E2=80=99t see the objectionable syntax anywhere in there. Perhaps you=
could be more specific.
> template <typename... Ts>
> int hash(std::tuple<Ts...> const &tup) {
> return helper<Ts...>::hash(tup, std::integer_sequence_for<Ts...>());
> }
>=20
> With __indexof() the body of the hash function for std::tuple reduces to:
>=20
> return (... ^ hash(std::get<__indexof(Ts)>(tup)));
You still didn=E2=80=99t use any "template <typename... Ts> template <sizeo=
f_t... Ns> nesting,=E2=80=9D at least not per se.
Anyway, given a sequence pack operator, call it unpack_sequence, you wouldn=
=E2=80=99t need to declare anything extra. The function would also be gener=
ically applicable to tuple-like types. The entire solution is reduced to:
template < typename tuple_like >
int hash(tuple_like const &tup) {
return hash( ... ^ std::get< unpack_sequence( std::tuple_size< tuple_lik=
e >::value ) >( tup ) );
}
> Seems like, if you're going to go this route, you'd want something like t=
he N3723 someone mentioned earlier in this thread. That's a vastly bigger a=
nd more invasive feature than what I was proposing here, tho. Plus, I get t=
he sense that the two are orthogonal: you could still benefit from an __ind=
exof() as a simpler alternative to marshalling all that parameter pack mani=
pulation machinery N3723 proposes.
An unpack_sequence operator would be self-contained. N3728 is about droppin=
g std::tuple from std::tuple< a, b, c > such that <a, b, c> is its own enti=
ty. There=E2=80=99s no particular connection.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_03D04176-22BE-4281-AB3B-537A9C964DAB
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9307=
=E2=80=9323, at 9:27 PM, Ryan Johnson <<a href=3D"mailto:scovich@gmail.c=
om" class=3D"">scovich@gmail.com</a>> wrote:</div><br class=3D"Apple-int=
erchange-newline"><div class=3D"">
=20
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
" class=3D"">
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<div class=3D"moz-cite-prefix">On 23/07/2015 6:48 AM, David Krauss
wrote:<br class=3D"">
</div>
<blockquote cite=3D"mid:A526687A-5EA3-4562-91C7-47EE886A1767@mac.com" t=
ype=3D"cite" class=3D"">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8" class=3D"">
<br class=3D"">
<div class=3D"">
<blockquote type=3D"cite" class=3D"">
<div class=3D"">On 2015=E2=80=9307=E2=80=9323, at 7:59 PM, Ryan J=
ohnson <<a moz-do-not-send=3D"true" href=3D"mailto:scovich@gmail.com" cl=
ass=3D"">scovich@gmail.com</a>> wrote:</div>
<br class=3D"Apple-interchange-newline">
<div class=3D"">
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Cont=
ent-Type" class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<div class=3D"moz-cite-prefix">On 23/07/2015 12:52 AM, David
Krauss wrote:<br class=3D"">
</div>
<blockquote cite=3D"mid:2919925F-0AD4-4829-91FB-72979643229A@=
gmail.com" type=3D"cite" class=3D"">
<meta http-equiv=3D"Content-Type" content=3D"text/html;
charset=3Dutf-8" class=3D"">
<br class=3D"">
<div class=3D"">
<div class=3D"">That=E2=80=99s why I suggested an alias
template. Alias template substitutions occur before
argument substitutions or type deduction. So, the
usage</div>
<div class=3D""><br class=3D"">
</div>
<font class=3D"" face=3D"Courier">template <typename
... Ts, std::size_t ... Xs><br class=3D"">
std::vector<std::size_t> foo(
std::indexed_type< Ts, Xs > && ...) {
return {Xs...}; }</font></div>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">gets transformed into something like</div>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">
<div class=3D""><font class=3D"" face=3D"Courier">templat=
e
<typename ... Ts, std::size_t ... Xs><br class=
=3D"">
std::vector<std::size_t> foo( Ts [[__index
(Xs)]] && ...) { return {Xs...}; }</font></di=
v>
<div class=3D""><font class=3D"" face=3D"Courier"><br cla=
ss=3D"">
</font></div>
<div class=3D"">What I=E2=80=99m trying to illustrate her=
e is
that the parameter type will be <font class=3D"" face=
=3D"Courier">Ts &&</font> regardless of
the <font class=3D"" face=3D"Courier">Xs</font> values,
but <span style=3D"font-family: Courier;" class=3D=
"">Xs</span> can
still be deduced from the context where the alias
template was used, because the alias template has
been substituted away before deduction begins.</div>
</div>
</blockquote>
OK, I read that too quickly before and didn't "get" that
std::indexed_type<Ts,Xs> *is* Ts. <br class=3D"">
<br class=3D"">
However, the compiler won't know that, and I'm still
struggling to see how the code you propose could actually
compile. I'm not aware of any case where today's compilers
can "work backward" from a function arg whose type is both
instantiation-dependent and type-dependent on T, and
successfully infer what T should be (unless T is also used
directly). <br class=3D"">
</div>
</div>
</blockquote>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">Since C++11, this will compile:</div>
<div class=3D""><br class=3D"">
</div>
<div class=3D""><font class=3D"" face=3D"Courier">template< type=
name t ></font></div>
<div class=3D""><font class=3D"" face=3D"Courier">using same_type =
=3D t;</font></div>
<div class=3D""><font class=3D"" face=3D"Courier"><br class=3D"">
</font></div>
<div class=3D""><font class=3D"" face=3D"Courier">template< type=
name t ></font></div>
<div class=3D""><font class=3D"" face=3D"Courier">t id( same_type&l=
t; t >
value ) { return value; }</font></div>
<div class=3D""><font class=3D"" face=3D"Courier"><br class=3D"">
</font></div>
<div class=3D""><font class=3D"" face=3D"Courier">int q =3D id( 3 )=
;</font></div>
<div class=3D""><br class=3D"">
</div>
<div class=3D""><font class=3D"" face=3D"Courier">same_type</font> =
is an alias
template, hence it is substituted before deduction. There=E2=80=
=99s no
working backward.</div>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">My suggestion is to add a hidden deduced context, e=
..g. in
an internal attribute. That=E2=80=99s what the compiler would kno=
w
about.</div>
</div>
</blockquote>
The part that worries me is this code does not compile:<br class=3D"">
<br class=3D"">
<tt class=3D"">template <typename T, size_t N=3D0></tt><tt class=
=3D""><br class=3D""></tt></div></div></blockquote><div><br class=3D""></di=
v><div>What=E2=80=99s the default argument for?</div><br class=3D""><blockq=
uote type=3D"cite" class=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=
=3D"#000000" class=3D""><tt class=3D"">
</tt><tt class=3D"">using indexed_type =3D T;</tt><tt class=3D""><br cl=
ass=3D"">
</tt><tt class=3D""><br class=3D"">
</tt><tt class=3D"">template <typename T, typename N></tt><tt cla=
ss=3D""><br class=3D"">
</tt><tt class=3D"">size_t foo(indexed_type<T,N> &&) { re=
</tt><tt class=3D"">turn
N; }</tt><tt class=3D""><br class=3D"">
</tt><tt class=3D""><br class=3D"">
</tt><tt class=3D"">int main() { return foo("hi");</tt><tt class=3D""> =
}</tt><tt class=3D""><br class=3D"">
</tt><br class=3D"">
Because the compiler cannot figure out how to come up with N while
instantiating foo. On gcc-4.9 for example:<br class=3D""></div></div></=
blockquote><div><br class=3D""></div><div>Yes, that is the hidden magic. It=
=E2=80=99s not a pure library solution. It=E2=80=99s a library <i class=3D"=
">interface</i> with no need to add new syntax.</div><div><br class=3D=
""></div><div>(What were you expecting? There are no instructions for seque=
ntial counting in that program.)</div><br class=3D""><blockquote type=3D"ci=
te" class=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#000000" cl=
ass=3D"">I fail to see how adding magic to indexed_type, so that N takes a
meaningful value, would get past the deduction failure that has
already occurred before the compiler ever tried to instantiate
indexed_type.</div></div></blockquote><blockquote type=3D"cite" class=
=3D""><br class=3D""></blockquote><blockquote type=3D"cite" class=3D""><div=
class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">Today's co=
mpiler can't work backwards from the magical
N of indexed_type in order to deduce the ordinary N of foo; type
aliases do not change that situation as far as I can tell---your
example compiles because the user has already supplied T and so
alias substitution can go ahead; the user has *not* supplied N and
so the compiler is unable to continue.<br class=3D""></div></div></bloc=
kquote><div><br class=3D""></div><div>The user doesn=E2=80=99t supply N, de=
duction (the =E2=80=9Ccompiler magic=E2=80=9D) does. I illustrated it as an=
attribute:</div><div><br class=3D""></div><div><font face=3D"Courier" clas=
s=3D"">template <typename ... Ts, std::size_t ... Xs><br class=3D"">s=
td::vector<std::size_t> foo( Ts [[__index (Xs)]] && ...) { re=
turn {Xs...}; }<br class=3D""></font><br class=3D""></div><div><font face=
=3D"Courier" class=3D"">__index(Xs)</font> is the deduced context. The doub=
le brackets are unnecessary, serving only for illustrative syntactic orient=
ation. For comparison, consider this:</div><div><br class=3D""></div><div><=
font face=3D"Courier" class=3D"">template< typename t, std::size_t v >=
;<br class=3D"">using ic =3D std::integral_constant< t, v >;<br class=
=3D""><br class=3D"">template <typename ... Ts, std::size_t ... Xs><b=
r class=3D"">std::vector<std::size_t> foo( ic< Ts, Xs > ...) { =
return {Xs...}; }<br class=3D""></font><br class=3D""></div><div><span styl=
e=3D"font-family: Courier;" class=3D"">int main() {</span></div><font face=
=3D"Courier" class=3D""> auto v =3D foo( std::integral_co=
nstant< std::size_t, 3 >{}, std::integral_constant< std::size_t, 4=
2 >{} );<br class=3D""></font><span style=3D"font-family: Courier;" clas=
s=3D"">}</span><font face=3D"Courier" class=3D""><br class=3D""></font><div=
><span style=3D"font-family: Courier;" class=3D""><br class=3D""></span></d=
iv><div>This is valid C++11. The compiler doesn=E2=80=99t need the argument=
s of template parameters in order to substitute them into an alias template=
.. (Default template arguments of alias templates don=E2=80=99t work the sam=
e way, so you might get confused if you tend to add default arguments every=
where. I never suggested any default arguments.)</div><div><br class=3D""><=
/div><blockquote type=3D"cite" class=3D""><div class=3D""><div bgcolor=3D"#=
FFFFFF" text=3D"#000000" class=3D"">
=20
That's the part I was hoping you could elaborate on.<br class=3D""></di=
v></div></blockquote><div><blockquote type=3D"cite" class=3D""><br class=3D=
""></blockquote></div><blockquote type=3D"cite" class=3D""><div class=3D"">=
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D""><blockquote cite=3D"mi=
d:A526687A-5EA3-4562-91C7-47EE886A1767@mac.com" type=3D"cite" class=3D""><d=
iv class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div bgc=
olor=3D"#FFFFFF" text=3D"#000000" class=3D"">Actually,
that's a good point, and the whole point of this proposal
is drastically reduce the need for `template
<typename... Ts> template <sizeof_t... Ns>'
nesting that's often required for working with std::tuple.
</div>
</div>
</blockquote>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">Can you cite some code with this symptom? The probl=
em
doesn=E2=80=99t look familiar to me.</div>
</div>
</blockquote>
The code examples I cited in my original message can all be cast to
use integer sequences instead of recursion; we chose to go with
recursion rather than a variadic template helper function that takes
a std::integer_sequence as an argument (following advice that
variadic templates are slow and should be avoided when possible). <br c=
lass=3D""></div></div></blockquote><div><br class=3D""></div><div>Huh? =
;<font face=3D"Courier" class=3D"">std::tuple_element</font> is not sl=
ower than a recursive template that reinvents it. Parameter packs are usual=
ly faster than recursive templates. Recursive templates are the C++98-era s=
olution.</div><div class=3D""><br class=3D""></div><div>The <font face=3D"C=
ourier" class=3D"">GenSequence</font> example makes it look like you were u=
naware of the existence of <font face=3D"Courier" class=3D"">std::make_inde=
x_sequence</font>.</div><div><br class=3D""></div><blockquote type=3D"cite"=
class=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=
=3D"">The documentation for std::integer_sequence has some nice examples:<b=
r class=3D"">
<a class=3D"moz-txt-link-freetext" href=3D"http://en.cppreference.com/w=
/cpp/utility/integer_sequence">http://en.cppreference.com/w/cpp/utility/int=
eger_sequence</a><br class=3D"">
<br class=3D"">
Stack Overflow is crawling with questions on the theme of how to
turn <typename ...Ts> into <size_t ...Ns> when dealing
with tuples. Here are just a few that turned up when I searched for
"c++11 index tuple=E2=80=9D</div></div></blockquote><div><br class=3D""=
></div><div>I see. So "`template <typename... Ts> template <sizeof=
_t... Ns>=E2=80=99 nesting=E2=80=9D is referring to the practice of decl=
aring a nested class template, and then defining it out side the enclosing =
class definition. But why would someone write it that way?</div><br class=
=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div bgcolor=3D"=
#FFFFFF" text=3D"#000000" class=3D"">
=20
<a class=3D"moz-txt-link-freetext" href=3D"http://stackoverflow.com/questio=
ns/28997271/c11-way-to-index-tuple-at-runtime-without-using-switch">http://=
stackoverflow.com/questions/28997271/c11-way-to-index-tuple-at-runtime-with=
out-using-switch</a><br class=3D"">
<a class=3D"moz-txt-link-freetext" href=3D"http://stackoverflow.com/questio=
ns/27936332/c11-building-a-stdtuple-from-a-template-function">http://stacko=
verflow.com/questions/27936332/c11-building-a-stdtuple-from-a-template-func=
tion</a><br class=3D"">
<a class=3D"moz-txt-link-freetext" href=3D"http://stackoverflow.com/questio=
ns/17854219/creating-a-sub-tuple-starting-from-a-stdtuplesome-type">http://=
stackoverflow.com/questions/17854219/creating-a-sub-tuple-starting-from-a-s=
tdtuplesome-type</a><br class=3D""></div></div></blockquote><div><br class=
=3D""></div><div>I don=E2=80=99t see the objectionable syntax anywhere in t=
here. Perhaps you could be more specific.</div><br class=3D""><blockquote t=
ype=3D"cite" class=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#0=
00000" class=3D""><tt class=3D"">template <typename... Ts></tt><tt cl=
ass=3D""><br class=3D"">
</tt><tt class=3D"">int hash(std::tuple<Ts...> const &tup) {<=
/tt><tt class=3D""><br class=3D"">
</tt><tt class=3D""> return helper<Ts...>::</tt><tt c=
lass=3D"">hash(tup,
std::integer_sequence_for<Ts...>());<br class=3D"">
</tt><tt class=3D"">}</tt><br class=3D"">
<br class=3D"">
With __indexof() the body of the hash function for std::tuple
reduces to:<br class=3D"">
<br class=3D"">
<tt class=3D"">return (... ^ hash(std::get<__indexof(Ts)>(tup)));=
</tt><br class=3D""></div></div></blockquote><div><br class=3D""></div><div=
>You still didn=E2=80=99t use any "<font face=3D"Courier" class=3D"">templa=
te <typename... Ts> template <sizeof_t... Ns></font> nesti=
ng,=E2=80=9D at least not per se.</div><div><br class=3D""></div><div>Anywa=
y, given a sequence pack operator, call it <font face=3D"Courier" class=3D"=
">unpack_sequence</font>, you wouldn=E2=80=99t need to declare anything ext=
ra. The function would also be generically applicable to tuple-like types. =
The entire solution is reduced to:</div><div><br class=3D""></div><div><fon=
t face=3D"Courier" class=3D"">template < typename tuple_like ><br cla=
ss=3D"">int hash(tuple_like const &tup) {<br class=3D""> re=
turn hash( ... ^ std::get< </font><span style=3D"font-family: Couri=
er;" class=3D"">unpack_sequence</span><font face=3D"Courier" class=3D"">( s=
td::tuple_size< tuple_like >::value ) >( tup ) );<br class=3D"">}<=
br class=3D""></font></div><div><br class=3D""></div></div><div><blockquote=
type=3D"cite" class=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"=
#000000" class=3D"">
Seems like, if you're going to go this route, you'd want something
like the N3723 someone mentioned earlier in this thread. That's a
vastly bigger and more invasive feature than what I was proposing
here, tho. Plus, I get the sense that the two are orthogonal: you
could still benefit from an __indexof() as a simpler alternative to
marshalling all that parameter pack manipulation machinery N3723
proposes.<br class=3D""></div></div></blockquote><br class=3D""></div><=
div>An <span style=3D"font-family: Courier;" class=3D"">unpack_sequenc=
e</span> operator would be self-contained. N3728 is about dropping <fo=
nt face=3D"Courier" class=3D"">std::tuple</font> from <font face=3D"Courier=
" class=3D"">std::tuple< a, b, c ></font> such that <font face=
=3D"Courier" class=3D""><a, b, c></font> is its own entity. There=E2=
=80=99s no particular connection.</div><div><br class=3D""></div></body></h=
tml>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_03D04176-22BE-4281-AB3B-537A9C964DAB--
.
Author: Edward Catmur <ed@catmur.co.uk>
Date: Fri, 24 Jul 2015 05:40:26 -0700 (PDT)
Raw View
------=_Part_354_51733225.1437741626835
Content-Type: multipart/alternative;
boundary="----=_Part_355_704602076.1437741626836"
------=_Part_355_704602076.1437741626836
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Friday, 24 July 2015 04:06:43 UTC+1, David Krauss wrote:
>
> An unpack_sequence operator would be self-contained. N3728 is about=20
> dropping std::tuple from std::tuple< a, b, c > such that <a, b, c> is its=
=20
> own entity. There=E2=80=99s no particular connection.
>
N3728 is about having typelists that can be returned by metafunctions and=
=20
unpacked directly, rather than having to be passed in (down the stack or=20
metastack) to be inferred as parameter packs. It mentions std::tuple only=
=20
in context of the somewhat prevalent usage of std::tuple as a typelist=20
vocabulary type; N3728 typelists can't be instantiated so they don't=20
replace std::tuple as a runtime data type.
In this case, the connection would be that the library can given N generate=
=20
a typelist for the sequence 0..N-1 that can be unpacked directly:
template < typename tuple_like >
int hash(tuple_like const &tup) {
return ... ^ hash( std::get< std::make_index_sequence_v< std::tuple_size=
<=20
tuple_like >::value > >( tup ) );
} // ^-- metafunction returning typelist 0..N-1
As Ryan has mentioned, N3728 is a more extensive feature than indexof -=20
although arguably less "magic".
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_355_704602076.1437741626836
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, 24 July 2015 04:06:43 UTC+1, David Krauss wrot=
e:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:brea=
k-word"><div>An=C2=A0<span style=3D"font-family:Courier">unpack_sequence</s=
pan>=C2=A0operator would be self-contained. N3728 is about dropping <font f=
ace=3D"Courier">std::tuple</font> from <font face=3D"Courier">std::tuple<=
; a, b, c ></font>=C2=A0such that <font face=3D"Courier"><a, b, c>=
</font> is its own entity. There=E2=80=99s no particular connection.</div><=
/div></blockquote><div><br></div><div>N3728 is about having typelists that =
can be returned by metafunctions and unpacked directly, rather than having =
to be passed in (down the stack or metastack) to be inferred as parameter p=
acks. It mentions std::tuple only in context of the somewhat prevalent usag=
e of std::tuple as a typelist vocabulary type; N3728 typelists can't be=
instantiated so they don't replace std::tuple as a runtime data type.<=
/div><div><br></div><div>In this case, the connection would be that the lib=
rary can given N generate a typelist for the sequence 0..N-1 that can be un=
packed directly:</div><div><br></div><div class=3D"prettyprint" style=3D"bo=
rder: 1px solid rgb(187, 187, 187); word-wrap: break-word; background-color=
: rgb(250, 250, 250);"><code class=3D"prettyprint"><div class=3D"subprettyp=
rint"><span style=3D"color: #008;" class=3D"styled-by-prettify">template</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"> </span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">typename</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> tuple_like </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;" cla=
ss=3D"styled-by-prettify">int</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> hash</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">tuple_like </span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">const</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">tup</span><sp=
an 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>=C2=A0 =C2=A0</span><span style=3D"color: =
#008;" class=3D"styled-by-prettify">return</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"sty=
led-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">^</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
hash</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n><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: #008;" class=3D"styled-by-prettify">get</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> std</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">make_index_sequence_v</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify"><</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">tuple_size</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> tuple_like </span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">>::</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">value </span><span style=3D"color: #660;" class=3D"styled-by-prettify">&=
gt;</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"> tup </span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">)</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #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"st=
yled-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">=
// =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0^-- metafunction returning typelist 0..N-1</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div=
></code></div><div><br></div><div>As Ryan has mentioned, N3728 is a more ex=
tensive feature than indexof - although arguably less "magic".</d=
iv></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_355_704602076.1437741626836--
------=_Part_354_51733225.1437741626835--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Fri, 24 Jul 2015 11:39:19 -0600
Raw View
This is a multi-part message in MIME format.
--------------070104090004020403010805
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 24/07/2015 6:40 AM, Edward Catmur wrote:
> On Friday, 24 July 2015 04:06:43 UTC+1, David Krauss wrote:
>
> An unpack_sequence operator would be self-contained. N3728 is
> about dropping std::tuple from std::tuple< a, b, c > such that <a,
> b, c> is its own entity. There=E2=80=99s no particular connection.
>
>
> N3728 is about having typelists that can be returned by metafunctions=20
> and unpacked directly, rather than having to be passed in (down the=20
> stack or metastack) to be inferred as parameter packs. It mentions=20
> std::tuple only in context of the somewhat prevalent usage of=20
> std::tuple as a typelist vocabulary type; N3728 typelists can't be=20
> instantiated so they don't replace std::tuple as a runtime data type.
>
> In this case, the connection would be that the library can given N=20
> generate a typelist for the sequence 0..N-1 that can be unpacked directly=
:
>
> |
> template<typenametuple_like >
> inthash(tuple_like const&tup){
> return...^hash(std::get<std::make_index_sequence_v<std::tuple_size<tuple_=
like=20
> >::value >>(tup ));
> }// ^-- metafunction returning typelist 0..N-1
> |
>
> As Ryan has mentioned, N3728 is a more extensive feature than indexof=20
> - although arguably less "magic".
Do you have any sense of how likely your proposal is to be accepted?=20
Because if it got in, the need for __indexof() would decrease=20
precipitously... though it might still be convenient to have both around.
(David, I'm still digesting your email, a reply is in the works)
Ryan
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------070104090004020403010805
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 24/07/2015 6:40 AM, Edward Catmur
wrote:<br>
</div>
<blockquote
cite=3D"mid:7edf7b0a-d3db-424d-adcb-3d619765bab8@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">On Friday, 24 July 2015 04:06:43 UTC+1, David
Krauss wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div style=3D"word-wrap:break-word">
<div>An=C2=A0<span style=3D"font-family:Courier">unpack_sequenc=
e</span>=C2=A0operator
would be self-contained. N3728 is about dropping <font
face=3D"Courier">std::tuple</font> from <font
face=3D"Courier">std::tuple< a, b, c ></font>=C2=A0su=
ch
that <font face=3D"Courier"><a, b, c></font> is its
own entity. There=E2=80=99s no particular connection.</div>
</div>
</blockquote>
<div><br>
</div>
<div>N3728 is about having typelists that can be returned by
metafunctions and unpacked directly, rather than having to be
passed in (down the stack or metastack) to be inferred as
parameter packs. It mentions std::tuple only in context of the
somewhat prevalent usage of std::tuple as a typelist
vocabulary type; N3728 typelists can't be instantiated so they
don't replace std::tuple as a runtime data type.</div>
<div><br>
</div>
<div>In this case, the connection would be that the library can
given N generate a typelist for the sequence 0..N-1 that can
be unpacked directly:</div>
<div><br>
</div>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187,
187); word-wrap: break-word; background-color: rgb(250, 250,
250);"><code class=3D"prettyprint">
<div class=3D"subprettyprint"><span style=3D"color: #008;"
class=3D"styled-by-prettify">template</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
style=3D"color: #660;" class=3D"styled-by-prettify"><</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
style=3D"color: #008;" class=3D"styled-by-prettify">typenam=
e</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
tuple_like </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">int</span><span style=3D"color=
:
#000;" class=3D"styled-by-prettify"> hash</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span
style=3D"color: #000;" class=3D"styled-by-prettify">tuple_l=
ike
</span><span style=3D"color: #008;"
class=3D"styled-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">tup</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: #660;" class=3D"styled-by-prettify">{</span=
><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
=C2=A0 =C2=A0</span><span style=3D"color: #008;"
class=3D"styled-by-prettify">return</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span
style=3D"color: #660;" class=3D"styled-by-prettify">...</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: #000;" class=3D"styled-by-prettify"> hash</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span
style=3D"color: #000;" class=3D"styled-by-prettify"> std</s=
pan><span
style=3D"color: #660;" class=3D"styled-by-prettify">::</spa=
n><span
style=3D"color: #008;" class=3D"styled-by-prettify">get</sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify"><</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify"> std</s=
pan><span
style=3D"color: #660;" class=3D"styled-by-prettify">::</spa=
n><span
style=3D"color: #000;" class=3D"styled-by-prettify">make_in=
dex_sequence_v</span><span
style=3D"color: #660;" class=3D"styled-by-prettify"><</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify"> std</s=
pan><span
style=3D"color: #660;" class=3D"styled-by-prettify">::</spa=
n><span
style=3D"color: #000;" class=3D"styled-by-prettify">tuple_s=
ize</span><span
style=3D"color: #660;" class=3D"styled-by-prettify"><</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify">
tuple_like </span><span style=3D"color: #660;"
class=3D"styled-by-prettify">>::</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">value <=
/span><span
style=3D"color: #660;" class=3D"styled-by-prettify">></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"> tup </=
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">);</spa=
n><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"> </span><span
style=3D"color: #800;" class=3D"styled-by-prettify">// =C2=
=A0 =C2=A0 =C2=A0
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0^-- metafunction returning typelist
0..N-1</span><span style=3D"color: #000;"
class=3D"styled-by-prettify"><br>
</span></div>
</code></div>
<div><br>
</div>
<div>As Ryan has mentioned, N3728 is a more extensive feature
than indexof - although arguably less "magic".</div>
</div>
</blockquote>
Do you have any sense of how likely your proposal is to be accepted?
Because if it got in, the need for __indexof() would decrease
precipitously... though it might still be convenient to have both
around.<br>
<br>
(David, I'm still digesting your email, a reply is in the works)<br>
<br>
Ryan<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------070104090004020403010805--
.
Author: Edward Catmur <ed@catmur.co.uk>
Date: Fri, 24 Jul 2015 10:52:06 -0700 (PDT)
Raw View
------=_Part_469_1857737868.1437760326250
Content-Type: multipart/alternative;
boundary="----=_Part_470_1381814171.1437760326250"
------=_Part_470_1381814171.1437760326250
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Ah, n3728 is not my proposal, it's from Mike Spertus (I'm just a bystander=
=20
here). Mike looks to be quite busy shepherding template argument type=20
deduction (n4469), variadic lock_guard (n4470) and constructor template=20
parameter deduction (n4471) through, but maybe he'll be able to pick n3728=
=20
back up at some point. (Really, I have absolutely no idea what its=20
prospects are.)
On Friday, 24 July 2015 18:39:29 UTC+1, Ryan Johnson wrote:
>
> On 24/07/2015 6:40 AM, Edward Catmur wrote:
> =20
> On Friday, 24 July 2015 04:06:43 UTC+1, David Krauss wrote:=20
>>
>> An unpack_sequence operator would be self-contained. N3728 is about=20
>> dropping std::tuple from std::tuple< a, b, c > such that <a, b, c> is=20
>> its own entity. There=E2=80=99s no particular connection.
>> =20
>
> N3728 is about having typelists that can be returned by metafunctions=20
> and unpacked directly, rather than having to be passed in (down the stack=
=20
> or metastack) to be inferred as parameter packs. It mentions std::tuple=
=20
> only in context of the somewhat prevalent usage of std::tuple as a typeli=
st=20
> vocabulary type; N3728 typelists can't be instantiated so they don't=20
> replace std::tuple as a runtime data type.
>
> In this case, the connection would be that the library can given N=20
> generate a typelist for the sequence 0..N-1 that can be unpacked directly=
:
>
> template < typename tuple_like >
> int hash(tuple_like const &tup) {
> return ... ^ hash( std::get< std::make_index_sequence_v< std::
> tuple_size< tuple_like >::value > >( tup ) );
> } // ^-- metafunction returning typelist 0..N-=
1
> =20
> As Ryan has mentioned, N3728 is a more extensive feature than indexof -=
=20
> although arguably less "magic".
> =20
> Do you have any sense of how likely your proposal is to be accepted?=20
> Because if it got in, the need for __indexof() would decrease=20
> precipitously... though it might still be convenient to have both around.
>
> (David, I'm still digesting your email, a reply is in the works)
>
> Ryan
>
>=20
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_470_1381814171.1437760326250
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Ah, n3728 is not my proposal, it's from Mike Spertus (=
I'm just a bystander here). Mike looks to be quite busy shepherding tem=
plate argument type deduction (n4469), variadic lock_guard (n4470) and cons=
tructor template parameter deduction (n4471) through, but maybe he'll b=
e able to pick n3728 back up at some point. (Really, I have absolutely no i=
dea what its prospects are.)<br><br>On Friday, 24 July 2015 18:39:29 UTC+1,=
Ryan Johnson wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>On 24/07/2015 6:40 AM, Edward Catmur
wrote:<br>
</div>
<blockquote type=3D"cite">
<div dir=3D"ltr">On Friday, 24 July 2015 04:06:43 UTC+1, David
Krauss wrote:
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex">
<div style=3D"word-wrap:break-word">
<div>An=C2=A0<span style=3D"font-family:Courier">unpack_sequenc=
e</span>=C2=A0operator
would be self-contained. N3728 is about dropping <font face=
=3D"Courier">std::tuple</font> from <font face=3D"Courier">std::tuple< a=
, b, c ></font>=C2=A0such
that <font face=3D"Courier"><a, b, c></font> is its
own entity. There=E2=80=99s no particular connection.</div>
</div>
</blockquote>
<div><br>
</div>
<div>N3728 is about having typelists that can be returned by
metafunctions and unpacked directly, rather than having to be
passed in (down the stack or metastack) to be inferred as
parameter packs. It mentions std::tuple only in context of the
somewhat prevalent usage of std::tuple as a typelist
vocabulary type; N3728 typelists can't be instantiated so the=
y
don't replace std::tuple as a runtime data type.</div>
<div><br>
</div>
<div>In this case, the connection would be that the library can
given N generate a typelist for the sequence 0..N-1 that can
be unpacked directly:</div>
<div><br>
</div>
<div style=3D"border:1px solid rgb(187,187,187);word-wrap:break-wor=
d;background-color:rgb(250,250,250)"><code>
<div><span style=3D"color:#008">template</span><span style=3D"c=
olor:#000"> </span><span style=3D"color:#660"><</span><span style=3D"col=
or:#000"> </span><span style=3D"color:#008">typename</span><span style=3D"c=
olor:#000">
tuple_like </span><span style=3D"color:#660">></span><sp=
an style=3D"color:#000"><br>
</span><span style=3D"color:#008">int</span><span style=3D"co=
lor:#000"> hash</span><span style=3D"color:#660">(</span><span style=3D"col=
or:#000">tuple_like
</span><span style=3D"color:#008">const</span><span style=3D"=
color:#000"> </span><span style=3D"color:#660">&</span><span style=3D"c=
olor:#000">tup</span><span style=3D"color:#660">)</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#660">{</span><span style=3D"color:#00=
0"><br>
=C2=A0 =C2=A0</span><span style=3D"color:#008">return</span=
><span style=3D"color:#000"> </span><span style=3D"color:#660">...</span><s=
pan style=3D"color:#000"> </span><span style=3D"color:#660">^</span><span s=
tyle=3D"color:#000"> hash</span><span style=3D"color:#660">(</span><span st=
yle=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span sty=
le=3D"color:#008">get</span><span style=3D"color:#660"><</span><span sty=
le=3D"color:#000"> std</span><span style=3D"color:#660">::</span><span styl=
e=3D"color:#000">make_index_sequence_v</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">tuple_size</span><span style=3D"color:#66=
0"><</span><span style=3D"color:#000">
tuple_like </span><span style=3D"color:#660">>::</span><=
span style=3D"color:#000">value </span><span style=3D"color:#660">></spa=
n><span style=3D"color:#000"> </span><span style=3D"color:#660">>(</span=
><span style=3D"color:#000"> tup </span><span style=3D"color:#660">)</span>=
<span style=3D"color:#000"> </span><span style=3D"color:#660">);</span><spa=
n style=3D"color:#000"><br>
</span><span style=3D"color:#660">}</span><span style=3D"colo=
r:#000"> </span><span style=3D"color:#800">// =C2=A0 =C2=A0 =C2=A0
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0^-- metafunction returning typelist
0..N-1</span><span style=3D"color:#000"><br>
</span></div>
</code></div>
<div><br>
</div>
<div>As Ryan has mentioned, N3728 is a more extensive feature
than indexof - although arguably less "magic".</div>
</div>
</blockquote>
Do you have any sense of how likely your proposal is to be accepted?
Because if it got in, the need for __indexof() would decrease
precipitously... though it might still be convenient to have both
around.<br>
<br>
(David, I'm still digesting your email, a reply is in the works)<br=
>
<br>
Ryan<br>
<br>
</div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_470_1381814171.1437760326250--
------=_Part_469_1857737868.1437760326250--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Fri, 24 Jul 2015 14:33:57 -0600
Raw View
This is a multi-part message in MIME format.
--------------070801000700070107020102
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 23/07/2015 9:06 PM, David Krauss wrote:
>
>> On 2015=E2=80=9307=E2=80=9323, at 9:27 PM, Ryan Johnson <scovich@gmail.c=
om=20
>> <mailto:scovich@gmail.com>> wrote:
>>
>> On 23/07/2015 6:48 AM, David Krauss wrote:
>>>
>>>> On 2015=E2=80=9307=E2=80=9323, at 7:59 PM, Ryan Johnson <scovich@gmail=
..com=20
>>>> <mailto:scovich@gmail.com>> wrote:
>>>>
>>>> On 23/07/2015 12:52 AM, David Krauss wrote:
>>>>>
>>>>> That=E2=80=99s why I suggested an alias template. Alias template=20
>>>>> substitutions occur before argument substitutions or type=20
>>>>> deduction. So, the usage
>>>>>
>>>>> template <typename ... Ts, std::size_t ... Xs>
>>>>> std::vector<std::size_t> foo( std::indexed_type< Ts, Xs > && ...)=20
>>>>> { return {Xs...}; }
>>>>>
>>>>> gets transformed into something like
>>>>>
>>>>> template <typename ... Ts, std::size_t ... Xs>
>>>>> std::vector<std::size_t> foo( Ts [[__index (Xs)]] && ...) { return=20
>>>>> {Xs...}; }
>>>>>
>>>>> What I=E2=80=99m trying to illustrate here is that the parameter type=
will=20
>>>>> be Ts && regardless of the Xs values, but Xs can still be deduced=20
>>>>> from the context where the alias template was used, because the=20
>>>>> alias template has been substituted away before deduction begins.
>>>> OK, I read that too quickly before and didn't "get" that=20
>>>> std::indexed_type<Ts,Xs> *is* Ts.
>>>>
>>>> However, the compiler won't know that, and I'm still struggling to=20
>>>> see how the code you propose could actually compile. I'm not aware=20
>>>> of any case where today's compilers can "work backward" from a=20
>>>> function arg whose type is both instantiation-dependent and=20
>>>> type-dependent on T, and successfully infer what T should be=20
>>>> (unless T is also used directly).
>>>
>>> Since C++11, this will compile:
>>>
>>> template< typename t >
>>> using same_type =3D t;
>>>
>>> template< typename t >
>>> t id( same_type< t > value ) { return value; }
>>>
>>> int q =3D id( 3 );
>>>
>>> same_type is an alias template, hence it is substituted before=20
>>> deduction. There=E2=80=99s no working backward.
>>>
>>> My suggestion is to add a hidden deduced context, e.g. in an=20
>>> internal attribute. That=E2=80=99s what the compiler would know about.
>> The part that worries me is this code does not compile:
>>
>> template <typename T, size_t N=3D0>
>
> What=E2=80=99s the default argument for?
A stand-in for the missing compiler magic. Makes N available without the=20
user having to specify it directly. Though I start to get the impression=20
you want the magic to happen directly in the signature/declaration of=20
foo, triggered by the compiler's recognizing the (otherwise utterly=20
mundane) std::indexed_type?
>
>> using indexed_type =3D T;
>>
>> template <typename T, typename N>
>> size_t foo(indexed_type<T,N> &&) { return N; }
>>
>> int main() { return foo("hi");}
>>
>> Because the compiler cannot figure out how to come up with N while=20
>> instantiating foo. On gcc-4.9 for example:
>
> Yes, that is the hidden magic. It=E2=80=99s not a pure library solution. =
It=E2=80=99s=20
> a library /interface/ with no need to add new syntax.
You still haven't given any hint of how this hidden magic you propose=20
would be compatible with standard C++ template selection, see below.
>> I fail to see how adding magic to indexed_type, so that N takes a=20
>> meaningful value, would get past the deduction failure that has=20
>> already occurred before the compiler ever tried to instantiate=20
>> indexed_type.
>>
>> Today's compiler can't work backwards from the magical N of=20
>> indexed_type in order to deduce the ordinary N of foo; type aliases=20
>> do not change that situation as far as I can tell---your example=20
>> compiles because the user has already supplied T and so alias=20
>> substitution can go ahead; the user has *not* supplied N and so the=20
>> compiler is unable to continue.
>
> The user doesn=E2=80=99t supply N, deduction (the =E2=80=9Ccompiler magic=
=E2=80=9D) does. I=20
> illustrated it as an attribute:
>
> template <typename ... Ts, std::size_t ... Xs>
> std::vector<std::size_t> foo( Ts [[__index (Xs)]] && ...) { return=20
> {Xs...}; }
>
> __index(Xs) is the deduced context. The double brackets are=20
> unnecessary, serving only for illustrative syntactic orientation. For=20
> comparison, consider this:
>
> template< typename t, std::size_t v >
> using ic =3D std::integral_constant< t, v >;
>
> template <typename ... Ts, std::size_t ... Xs>
> std::vector<std::size_t> foo( ic< Ts, Xs > ...) { return {Xs...}; }
>
> int main() {
> auto v =3D foo( std::integral_constant< std::size_t, 3 >{},=20
> std::integral_constant< std::size_t, 42 >{} );
> }
>
> This is valid C++11. The compiler doesn=E2=80=99t need the arguments of=
=20
> template parameters in order to substitute them into an alias=20
> template. (Default template arguments of alias templates don=E2=80=99t wo=
rk=20
> the same way, so you might get confused if you tend to add default=20
> arguments everywhere. I never suggested any default arguments.)
Eh??? The compiler most certainly needs the arguments if it is to=20
substitute them. The above code is valid C++11 precisely because the=20
caller provides both the Ts and Xs when calling foo(). The template=20
alias does nothing to change that, it merely provides a shorter name for=20
std::integral_constant.
If I understand correctly, you are proposing to make foo() itself=20
magical, with the magic triggered by the appearance of an otherwise=20
mundane std::indexed_type in its signature, or by some variable=20
attribute affixed to the args. The problem is, the way template=20
deduction works in C++, the compiler will not even consider foo()=20
because the Xs cannot be deduced from information supplied *at the call=20
site* and so it will never see the bits that are supposed to trigger the=20
magic that would provide Xs.
Changing that behavior would be a Big Deal, because it changes the=20
semantics of template selection---which would already be a big deal by=20
itself---in a way that requires the compiler to do significantly more=20
work for all template candidates (searching for bits of magic in their=20
signatures), when the vast majority of them will not actually make use=20
of the feature. I doubt the Committee would be interested in making such=20
a large change to the language to support such a small feature.
Now, I could have missed some key detail here. I am by no means an=20
authority on the C++ standard or compiler internals (though I know=20
enough about the latter to get myself in trouble, at least). If you know=20
of some clean way your suggestion could actually be defined at the=20
language level and implemented in a compiler, I'd be delighted to hear=20
details about it.
>>>> Actually, that's a good point, and the whole point of this proposal=20
>>>> is drastically reduce the need for `template <typename... Ts>=20
>>>> template <sizeof_t... Ns>' nesting that's often required for=20
>>>> working with std::tuple.
>>>
>>> Can you cite some code with this symptom? The problem doesn=E2=80=99t l=
ook=20
>>> familiar to me.
>> The code examples I cited in my original message can all be cast to=20
>> use integer sequences instead of recursion; we chose to go with=20
>> recursion rather than a variadic template helper function that takes=20
>> a std::integer_sequence as an argument (following advice that=20
>> variadic templates are slow and should be avoided when possible).
>
> Huh? std::tuple_element is not slower than a recursive template that=20
> reinvents it. Parameter packs are usually faster than recursive=20
> templates. Recursive templates are the C++98-era solution.
>
> The GenSequence example makes it look like you were unaware of the=20
> existence of std::make_index_sequence.
I know about std::index_sequence and std::make_index_sequence (see=20
below). GenSequence came from our code base, which is C++11-only because=20
the versions of gcc we can use don't support C++14 yet.
Anyway, recursion is alive and well in C++11 and beyond, though perhaps=20
we've gotten better at hiding that fact behind standardized types. Huge=20
amounts of meta-programming techniques rely on various flavors of=20
recursion. Many of the various template helpers in the STL are=20
recursive---std::make_index_sequence and std::tuple being especially=20
relevant to this discussion.
That said, it's true that we're slowly moving away from recursion as the=20
be-all/end-all. C++11 variadic templates start to address some reasons=20
we use recursion so much, as do its restricted constexpr functions.=20
C++14 std::index_sequence helps a bit (by at least hiding some kinds of=20
recursion in a library class), and its generalized constexpr=20
functions-help a lot (by moving more complex meta-computations to=20
function rather than template code); C++17 fold expressions are another=20
big step (by eliminating recursion entirely from compatible kinds of=20
computations). Most of those approaches don't eliminate the explosion of=20
template helper functions, though (fold expressions being a massive=20
exception to that claim).
This proposal is just trying to eliminate a source of recursion and/or=20
helper functions that these previous advances don't seem to have=20
covered. The main messiness that would be left is std::tuple and=20
std::get, both of which seem pretty difficult to achieve non-recursively.
>
>> The documentation for std::integer_sequence has some nice examples:
>> http://en.cppreference.com/w/cpp/utility/integer_sequence
>>
>> Stack Overflow is crawling with questions on the theme of how to turn=20
>> <typename ...Ts> into <size_t ...Ns> when dealing with tuples. Here=20
>> are just a few that turned up when I searched for "c++11 index tuple=E2=
=80=9D
>
> I see. So "`template <typename... Ts> template <sizeof_t... Ns>=E2=80=99=
=20
> nesting=E2=80=9D is referring to the practice of declaring a nested class=
=20
> template, and then defining it out side the enclosing class=20
> definition. But why would someone write it that way?
>
> I don=E2=80=99t see the objectionable syntax anywhere in [the StackOverfl=
ow=20
> links]. Perhaps you could be more specific.
>
>> template <typename... Ts>
>> int hash(std::tuple<Ts...> const &tup) {
>> return helper<Ts...>::hash(tup, std::integer_sequence_for<Ts...>());
>> }
>>
> You still didn=E2=80=99t use any "template <typename... Ts> template=20
> <sizeof_t... Ns> nesting,=E2=80=9D at least not per se.
The nesting is here:
template <typename... Ts> struct helper {
template <size_t... Ns>
static int hash(std::tuple<Ts...> const &tup,=20
std::index_sequence<Ns...>);
};
You could mask the nesting in various ways, for example by doing instead:
template <typename Tuple> struct helper2 {
template <size_t... Ns>
static int hash(Tuple const &tup, std::index_sequence<Ns...>);
};
But that doesn't change the complexity of the types the compiler has to=20
work with when instantiating the member function template:
int helper<int, float, double, bool>::hash<0ul, 1ul, 2ul, 3ul>(
std::tuple<int, float, double, bool> const&,
std::integer_sequence<unsigned long, 0ul, 1ul, 2ul, 3ul>)
vs.
int helper2<std::tuple<int, float, double, bool> >::hash<0ul, 1ul,=20
2ul, 3ul>(
std::tuple<int, float, double, bool> const&,
std::integer_sequence<unsigned long, 0ul, 1ul, 2ul, 3ul>)
If anything, the latter is slightly more complex, because it handles=20
tuple-like objects in addition to std::tuple. In contrast, with=20
__indexof or similar in place, you wouldn't have that second layer of=20
templating and would instead have only:
int hash<int, float, double, bool>
(std::tuple<int, float, double, bool> const&);
int hash2<std::tuple<int, float, double, bool> >
(std::tuple<int, float, double, bool> const&);
> template < typename tuple_like >
> int hash(tuple_like const &tup) {
> return hash( ... ^ std::get< unpack_sequence( std::tuple_size<=20
> tuple_like >::value ) >( tup ) );
> }
In contrast, your unpack_sequence would have to "hoist" an otherwise=20
non-pack statement, giving it a second set of variadic templates (the=20
size_t... sequence). N3728 would give something nearly identical. Both=20
create a new parameter pack to be unpacked, in addition to any packs=20
that were already present.
On the other hand, these "create-a-pack" approaches have the benefit of=20
*not* needing to explicitly bring in a <typename...> pack. That could be=20
useful at times, such as the tuple_like idiom you make a good argument=20
for using. Creating a pack also means the code won't care whether there=20
are other packs around; nor would it care whether those other packs are=20
type, non-type, or template template.
Thoughts?
Ryan
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------070801000700070107020102
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 23/07/2015 9:06 PM, David Krauss
wrote:<br>
</div>
<blockquote
cite=3D"mid:E4E74785-CF93-4DB2-865A-0CC760F28519@gmail.com"
type=3D"cite">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8">
<br class=3D"">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">On 2015=E2=80=9307=E2=80=9323, at 9:27 PM, Ryan J=
ohnson <<a
moz-do-not-send=3D"true" href=3D"mailto:scovich@gmail.com"
class=3D"">scovich@gmail.com</a>> wrote:</div>
<br class=3D"Apple-interchange-newline">
<div class=3D"">
<meta content=3D"text/html; charset=3Dutf-8"
http-equiv=3D"Content-Type" class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<div class=3D"moz-cite-prefix">On 23/07/2015 6:48 AM, David
Krauss wrote:<br class=3D"">
</div>
<blockquote
cite=3D"mid:A526687A-5EA3-4562-91C7-47EE886A1767@mac.com"
type=3D"cite" class=3D"">
<meta http-equiv=3D"Content-Type" content=3D"text/html;
charset=3Dutf-8" class=3D"">
<br class=3D"">
<div class=3D"">
<blockquote type=3D"cite" class=3D"">
<div class=3D"">On 2015=E2=80=9307=E2=80=9323, at 7:59 =
PM, Ryan
Johnson <<a moz-do-not-send=3D"true"
href=3D"mailto:scovich@gmail.com" class=3D"">scovic=
h@gmail.com</a>>
wrote:</div>
<br class=3D"Apple-interchange-newline">
<div class=3D"">
<meta content=3D"text/html; charset=3Dutf-8"
http-equiv=3D"Content-Type" class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<div class=3D"moz-cite-prefix">On 23/07/2015 12:52
AM, David Krauss wrote:<br class=3D"">
</div>
<blockquote
cite=3D"mid:2919925F-0AD4-4829-91FB-72979643229A@=
gmail.com"
type=3D"cite" class=3D"">
<meta http-equiv=3D"Content-Type"
content=3D"text/html; charset=3Dutf-8" class=3D=
"">
<br class=3D"">
<div class=3D"">
<div class=3D"">That=E2=80=99s why I suggested =
an
alias template. Alias template
substitutions occur before argument
substitutions or type deduction. So, the
usage</div>
<div class=3D""><br class=3D"">
</div>
<font class=3D"" face=3D"Courier">template
<typename ... Ts, std::size_t ...
Xs><br class=3D"">
std::vector<std::size_t> foo(
std::indexed_type< Ts, Xs >
&& ...) { return {Xs...}; }</font></d=
iv>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">gets transformed into something
like</div>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">
<div class=3D""><font class=3D"" face=3D"Courie=
r">template
<typename ... Ts, std::size_t ...
Xs><br class=3D"">
std::vector<std::size_t> foo( Ts
[[__index (Xs)]] && ...) {
return {Xs...}; }</font></div>
<div class=3D""><font class=3D"" face=3D"Courie=
r"><br
class=3D"">
</font></div>
<div class=3D"">What I=E2=80=99m trying to illu=
strate
here is that the parameter type will be <font
class=3D"" face=3D"Courier">Ts &&</=
font>
regardless of the <font class=3D""
face=3D"Courier">Xs</font> values, but=C2=
=A0<span
style=3D"font-family: Courier;" class=3D"">=
Xs</span>=C2=A0can
still be deduced from the context where
the alias template was used, because the
alias template has been substituted away
before deduction begins.</div>
</div>
</blockquote>
OK, I read that too quickly before and didn't
"get" that std::indexed_type<Ts,Xs> *is*
Ts. <br class=3D"">
<br class=3D"">
However, the compiler won't know that, and I'm
still struggling to see how the code you propose
could actually compile. I'm not aware of any
case where today's compilers can "work backward"
from a function arg whose type is both
instantiation-dependent and type-dependent on T,
and successfully infer what T should be (unless
T is also used directly). <br class=3D"">
</div>
</div>
</blockquote>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">Since C++11, this will compile:</div>
<div class=3D""><br class=3D"">
</div>
<div class=3D""><font class=3D"" face=3D"Courier">templat=
e<
typename t ></font></div>
<div class=3D""><font class=3D"" face=3D"Courier">using
same_type =3D t;</font></div>
<div class=3D""><font class=3D"" face=3D"Courier"><br
class=3D"">
</font></div>
<div class=3D""><font class=3D"" face=3D"Courier">templat=
e<
typename t ></font></div>
<div class=3D""><font class=3D"" face=3D"Courier">t id(
same_type< t > value ) { return value; }</font>=
</div>
<div class=3D""><font class=3D"" face=3D"Courier"><br
class=3D"">
</font></div>
<div class=3D""><font class=3D"" face=3D"Courier">int q =
=3D
id( 3 );</font></div>
<div class=3D""><br class=3D"">
</div>
<div class=3D""><font class=3D"" face=3D"Courier">same_ty=
pe</font>
is an alias template, hence it is substituted before
deduction. There=E2=80=99s no working backward.</div>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">My suggestion is to add a hidden deduced
context, e.g. in an internal attribute. That=E2=80=99s =
what
the compiler would know about.</div>
</div>
</blockquote>
The part that worries me is this code does not compile:<br
class=3D"">
<br class=3D"">
<tt class=3D"">template <typename T, size_t N=3D0></tt>=
<tt
class=3D""><br class=3D"">
</tt></div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>What=E2=80=99s the default argument for?</div>
</div>
</blockquote>
A stand-in for the missing compiler magic. Makes N available without
the user having to specify it directly. Though I start to get the
impression you want the magic to happen directly in the
signature/declaration of foo, triggered by the compiler's
recognizing the (otherwise utterly mundane) std::indexed_type? <br>
<br>
<blockquote
cite=3D"mid:E4E74785-CF93-4DB2-865A-0CC760F28519@gmail.com"
type=3D"cite">
<div><br class=3D"">
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D""><tt class=
=3D"">
</tt><tt class=3D"">using indexed_type =3D T;</tt><tt class=
=3D""><br
class=3D"">
</tt><tt class=3D""><br class=3D"">
</tt><tt class=3D"">template <typename T, typename N></=
tt><tt
class=3D""><br class=3D"">
</tt><tt class=3D"">size_t foo(indexed_type<T,N>
&&) { re</tt><tt class=3D"">turn N; }</tt><tt
class=3D""><br class=3D"">
</tt><tt class=3D""><br class=3D"">
</tt><tt class=3D"">int main() { return foo("hi");</tt><tt
class=3D""> }</tt><tt class=3D""><br class=3D"">
</tt><br class=3D"">
Because the compiler cannot figure out how to come up with
N while instantiating foo. On gcc-4.9 for example:<br
class=3D"">
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>Yes, that is the hidden magic. It=E2=80=99s not a pure library
solution. It=E2=80=99s a library <i class=3D"">interface</i>=C2=
=A0with no
need to add new syntax.</div>
</div>
</blockquote>
You still haven't given any hint of how this hidden magic you
propose would be compatible with standard C++ template selection,
see below.<br>
<br>
<blockquote
cite=3D"mid:E4E74785-CF93-4DB2-865A-0CC760F28519@gmail.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">I fail to =
see
how adding magic to indexed_type, so that N takes a
meaningful value, would get past the deduction failure
that has already occurred before the compiler ever tried
to instantiate indexed_type.</div>
</div>
</blockquote>
<blockquote type=3D"cite" class=3D""><br class=3D"">
</blockquote>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">Today's
compiler can't work backwards from the magical N of
indexed_type in order to deduce the ordinary N of foo;
type aliases do not change that situation as far as I can
tell---your example compiles because the user has already
supplied T and so alias substitution can go ahead; the
user has *not* supplied N and so the compiler is unable to
continue.<br class=3D"">
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>The user doesn=E2=80=99t supply N, deduction (the =E2=80=9Ccom=
piler magic=E2=80=9D)
does. I illustrated it as an attribute:</div>
<div><br class=3D"">
</div>
<div><font class=3D"" face=3D"Courier">template <typename ... Ts=
,
std::size_t ... Xs><br class=3D"">
std::vector<std::size_t> foo( Ts [[__index (Xs)]]
&& ...) { return {Xs...}; }<br class=3D"">
</font><br class=3D"">
</div>
<div><font class=3D"" face=3D"Courier">__index(Xs)</font> is the
deduced context. The double brackets are unnecessary, serving
only for illustrative syntactic orientation. For comparison,
consider this:</div>
<div><br class=3D"">
</div>
<div><font class=3D"" face=3D"Courier">template< typename t,
std::size_t v ><br class=3D"">
using ic =3D std::integral_constant< t, v >;<br class=3D"=
">
<br class=3D"">
template <typename ... Ts, std::size_t ... Xs><br
class=3D"">
std::vector<std::size_t> foo( ic< Ts, Xs > ...)
{ return {Xs...}; }<br class=3D"">
</font><br class=3D"">
</div>
<div><span style=3D"font-family: Courier;" class=3D"">int main() {<=
/span></div>
<font class=3D"" face=3D"Courier">=C2=A0 =C2=A0=C2=A0auto v =3D foo=
(
std::integral_constant< std::size_t, 3 >{},
std::integral_constant< std::size_t, 42 >{} );<br
class=3D"">
</font><span style=3D"font-family: Courier;" class=3D"">}</span><fo=
nt
class=3D"" face=3D"Courier"><br class=3D"">
</font>
<div><span style=3D"font-family: Courier;" class=3D""><br class=3D"=
">
</span></div>
<div>This is valid C++11. The compiler doesn=E2=80=99t need the
arguments of template parameters in order to substitute them
into an alias template. (Default template arguments of alias
templates don=E2=80=99t work the same way, so you might get confu=
sed
if you tend to add default arguments everywhere. I never
suggested any default arguments.)</div>
</div>
</blockquote>
Eh??? The compiler most certainly needs the arguments if it is to
substitute them. The above code is valid C++11 precisely because the
caller provides both the Ts and Xs when calling foo(). The template
alias does nothing to change that, it merely provides a shorter name
for std::integral_constant. <br>
<br>
If I understand correctly, you are proposing to make foo() itself
magical, with the magic triggered by the appearance of an otherwise
mundane std::indexed_type in its signature, or by some variable
attribute affixed to the args. The problem is, the way template
deduction works in C++, the compiler will not even consider foo()
because the Xs cannot be deduced from information supplied *at the
call site* and so it will never see the bits that are supposed to
trigger the magic that would provide Xs. <br>
<br>
Changing that behavior would be a Big Deal, because it changes the
semantics of template selection---which would already be a big deal
by itself---in a way that requires the compiler to do significantly
more work for all template candidates (searching for bits of magic
in their signatures), when the vast majority of them will not
actually make use of the feature. I doubt the Committee would be
interested in making such a large change to the language to support
such a small feature.<br>
<br>
Now, I could have missed some key detail here. I am by no means an
authority on the C++ standard or compiler internals (though I know
enough about the latter to get myself in trouble, at least). If you
know of some clean way your suggestion could actually be defined at
the language level and implemented in a compiler, I'd be delighted
to hear details about it.<br>
<br>
<blockquote
cite=3D"mid:E4E74785-CF93-4DB2-865A-0CC760F28519@gmail.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<blockquote
cite=3D"mid:A526687A-5EA3-4562-91C7-47EE886A1767@mac.com"
type=3D"cite" class=3D"">
<div class=3D"">
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">=
Actually,
that's a good point, and the whole point of this
proposal is drastically reduce the need for
`template <typename... Ts> template
<sizeof_t... Ns>' nesting that's often
required for working with std::tuple. </div>
</div>
</blockquote>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">Can you cite some code with this
symptom? The problem doesn=E2=80=99t look familiar to m=
e.</div>
</div>
</blockquote>
The code examples I cited in my original message can all
be cast to use integer sequences instead of recursion; we
chose to go with recursion rather than a variadic template
helper function that takes a std::integer_sequence as an
argument (following advice that variadic templates are
slow and should be avoided when possible). <br class=3D"">
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>Huh?=C2=A0<font class=3D"" face=3D"Courier">std::tuple_element=
</font>=C2=A0is
not slower than a recursive template that reinvents it.
Parameter packs are usually faster than recursive templates.
Recursive templates are the C++98-era solution.</div>
<div class=3D""><br class=3D"">
</div>
<div>The <font class=3D"" face=3D"Courier">GenSequence</font>
example makes it look like you were unaware of the existence
of <font class=3D"" face=3D"Courier">std::make_index_sequence</fo=
nt>.</div>
</div>
</blockquote>
I know about std::index_sequence and std::make_index_sequence (see
below). GenSequence came from our code base, which is C++11-only
because the versions of gcc we can use don't support C++14 yet. <br>
<br>
Anyway, recursion is alive and well in C++11 and beyond, though
perhaps we've gotten better at hiding that fact behind standardized
types. Huge amounts of meta-programming techniques rely on various
flavors of recursion. Many of the various template helpers in the
STL are recursive---std::make_index_sequence and std::tuple being
especially relevant to this discussion. <br>
<br>
That said, it's true that we're slowly moving away from recursion as
the be-all/end-all. C++11 variadic templates start to address some
reasons we use recursion so much, as do its restricted constexpr
functions. C++14 std::index_sequence helps a bit (by at least hiding
some kinds of recursion in a library class), and its generalized
constexpr functions-help a lot (by moving more complex
meta-computations to function rather than template code); C++17 fold
expressions are another big step (by eliminating recursion entirely
from compatible kinds of computations). Most of those approaches
don't eliminate the explosion of template helper functions, though
(fold expressions being a massive exception to that claim). <br>
<br>
This proposal is just trying to eliminate a source of recursion
and/or helper functions that these previous advances don't seem to
have covered. The main messiness that would be left is std::tuple
and std::get, both of which seem pretty difficult to achieve
non-recursively.<br>
<br>
<blockquote
cite=3D"mid:E4E74785-CF93-4DB2-865A-0CC760F28519@gmail.com"
type=3D"cite">
<div>
<div><br class=3D"">
</div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">The
documentation for std::integer_sequence has some nice
examples:<br class=3D"">
<a moz-do-not-send=3D"true" class=3D"moz-txt-link-freetext"
href=3D"http://en.cppreference.com/w/cpp/utility/integer_se=
quence">http://en.cppreference.com/w/cpp/utility/integer_sequence</a><br
class=3D"">
<br class=3D"">
Stack Overflow is crawling with questions on the theme of
how to turn <typename ...Ts> into <size_t
...Ns> when dealing with tuples. Here are just a few
that turned up when I searched for "c++11 index tuple=E2=80=
=9D</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>I see. So "`template <typename... Ts> template
<sizeof_t... Ns>=E2=80=99 nesting=E2=80=9D is referring to =
the practice
of declaring a nested class template, and then defining it out
side the enclosing class definition. But why would someone
write it that way?</div>
</div>
</blockquote>
<blockquote
cite=3D"mid:E4E74785-CF93-4DB2-865A-0CC760F28519@gmail.com"
type=3D"cite">
<div><br>
<div>I don=E2=80=99t see the objectionable syntax anywhere in [the
StackOverflow links]. Perhaps you could be more specific.</div>
<br class=3D"">
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D""><tt class=
=3D"">template
<typename... Ts></tt><tt class=3D""><br class=3D"">
</tt><tt class=3D"">int hash(std::tuple<Ts...> const
&tup) {</tt><tt class=3D""><br class=3D"">
</tt><tt class=3D"">=C2=A0=C2=A0 return helper<Ts...>::=
</tt><tt
class=3D"">hash(tup,
std::integer_sequence_for<Ts...>());<br class=3D"">
</tt><tt class=3D"">}</tt><br class=3D"">
<br>
</div>
</div>
</blockquote>
<div>You still didn=E2=80=99t use any "<font class=3D"" face=3D"Cou=
rier">template
<typename... Ts> template <sizeof_t... Ns></font>=
=C2=A0nesting,=E2=80=9D
at least not per se.</div>
</div>
</blockquote>
The nesting is here:<br>
<br>
<tt>template <typename... Ts> struct helper {<br>
=C2=A0=C2=A0 template <size_t... Ns><br>
=C2=A0=C2=A0 static int hash(std::tuple<Ts...> const &tup,
std::index_sequence<Ns...>);<br>
};</tt><br>
<br>
You could mask the nesting in various ways, for example by doing
instead: <br>
<br>
<tt>template <typename Tuple> struct helper2 {</tt><tt><br>
</tt><tt>=C2=A0=C2=A0 template <size_t... Ns></tt><tt><br>
</tt><tt>=C2=A0=C2=A0 static int hash(Tuple const &tup,
std::index_sequence<Ns...>);</tt><tt><br>
</tt><tt>};</tt><br>
<br>
But that doesn't change the complexity of the types the compiler has
to work with when instantiating the member function template:<br>
<br>
<tt>=C2=A0=C2=A0=C2=A0 int helper<int, float, double, bool>::hash=
<0ul,
1ul, 2ul, 3ul>(</tt><tt><br>
</tt><tt>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::tuple<int, =
float, double, bool>
const&, </tt><tt><br>
</tt><tt>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 </tt><tt>std::integ=
er_sequence<unsigned long,
0ul, 1ul, 2ul, 3ul>)</tt><tt><br>
</tt>vs. <br>
<tt><br>
=C2=A0=C2=A0=C2=A0 int helper2<std::tuple<int, float, double, b=
ool>
>::hash<0ul, 1ul, 2ul, 3ul>(</tt><tt><br>
</tt><tt>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 </tt><tt>std::tuple=
<int, float, double,
bool> const&, </tt><tt><br>
</tt><tt>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 </tt><tt>std::integ=
er_sequence<unsigned long,
0ul, 1ul, 2ul, 3ul>)</tt><br>
<br>
If anything, the latter is slightly more complex, because it handles
tuple-like objects in addition to std::tuple. In contrast, with
__indexof or similar in place, you wouldn't have that second layer
of templating and would instead have only:<br>
<br>
<tt>=C2=A0=C2=A0=C2=A0 int hash<int, float, double, bool><br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (std::tuple<int, float,=
double, bool> const&);</tt><br>
<tt><br>
=C2=A0=C2=A0=C2=A0 int hash2<std::tuple<int, float, double, boo=
l> ><br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (std::tuple<int, float,=
double, bool> const&);</tt><br>
<br>
<blockquote type=3D"cite"><font class=3D"" face=3D"Courier">template &l=
t;
typename tuple_like ><br class=3D"">
int hash(tuple_like const &tup) {<br class=3D"">
=C2=A0 =C2=A0return hash( ... ^ std::get<=C2=A0</font><span
style=3D"font-family: Courier;" class=3D"">unpack_sequence</span><f=
ont
class=3D"" face=3D"Courier">( std::tuple_size< tuple_like
>::value ) >( tup ) );<br class=3D"">
}</font></blockquote>
<br>
In contrast, your unpack_sequence would have to "hoist" an otherwise
non-pack statement, giving it a second set of variadic templates
(the size_t... sequence). N3728 would give something nearly
identical. Both create a new parameter pack to be unpacked, in
addition to any packs that were already present.<br>
<br>
On the other hand, these "create-a-pack" approaches have the benefit
of *not* needing to explicitly bring in a <typename...> pack.
That could be useful at times, such as the tuple_like idiom you make
a good argument for using. Creating a pack also means the code won't
care whether there are other packs around; nor would it care whether
those other packs are type, non-type, or template template. <br>
<br>
Thoughts?<br>
Ryan<br>
<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------070801000700070107020102--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Fri, 24 Jul 2015 14:39:36 -0600
Raw View
On 24/07/2015 11:52 AM, Edward Catmur wrote:
> Ah, n3728 is not my proposal, it's from Mike Spertus (I'm just a
> bystander here). Mike looks to be quite busy shepherding template
> argument type deduction (n4469), variadic lock_guard (n4470) and
> constructor template parameter deduction (n4471) through, but maybe
> he'll be able to pick n3728 back up at some point. (Really, I have
> absolutely no idea what its prospects are.)
Ah. N4471 will be really nice to have, and N4469 wouldn't be unwelcome
either. Go Mike!
Ryan
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: David Krauss <potswa@gmail.com>
Date: Sat, 25 Jul 2015 10:09:51 +0800
Raw View
--Apple-Mail=_897D65A9-0CE8-49A0-9991-2FD2AE6E9B22
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9307=E2=80=9325, at 4:33 AM, Ryan Johnson <scovich@gmail.co=
m> wrote:
>=20
> On 23/07/2015 9:06 PM, David Krauss wrote:
>>=20
>> What=E2=80=99s the default argument for?
> A stand-in for the missing compiler magic. Makes N available without the =
user having to specify it directly. Though I start to get the impression yo=
u want the magic to happen directly in the signature/declaration of foo, tr=
iggered by the compiler's recognizing the (otherwise utterly mundane) std::=
indexed_type?=20
The magic would happen in a modification to the type T generated by indexed=
_type<T>. In terms of the [[__index]] attribute:
// Standard library source code
template< typename type >
using indexed_type =3D Ts [[__index (Xs)]];
// User source code
template <typename ... Ts, std::size_t ... Xs>
std::vector<std::size_t> foo( std::indexed_type< Ts, Xs > && ...) { return =
{Xs...}; }
// After alias template substitution
template <typename ... Ts, std::size_t ... Xs>
std::vector<std::size_t> foo( Ts [[__index (Xs)]] && ...) { return {Xs...};=
}
// ^ both deduced ^
The implementation work would be in adding a new deduced context. (Again, t=
he implementation would not likely use actual double-bracket attribute synt=
ax, I=E2=80=99m just showing where such an internal keyword could fit in th=
e grammar.)
You could say that std::indexed_type would generate a magic signature, but =
only by applying ordinary alias template substitution to a magic keyword.
> If I understand correctly, you are proposing to make foo() itself magical=
, with the magic triggered by the appearance of an otherwise mundane std::i=
ndexed_type in its signature, or by some variable attribute affixed to the =
args. The problem is, the way template deduction works in C++, the compiler=
will not even consider foo() because the Xs cannot be deduced from informa=
tion supplied *at the call site* and so it will never see the bits that are=
supposed to trigger the magic that would provide Xs.=20
Parameters are deduced when they are mentioned in deduced contexts. If the =
compiler=E2=80=99s internals need an argument to correspond to the index se=
quence parameter, it can simply generate such a pack, upon encountering the=
magic keyword in the signature.
> Changing that behavior would be a Big Deal, because it changes the semant=
ics of template selection---which would already be a big deal by itself---i=
n a way that requires the compiler to do significantly more work for all te=
mplate candidates (searching for bits of magic in their signatures), when t=
he vast majority of them will not actually make use of the feature. I doubt=
the Committee would be interested in making such a large change to the lan=
guage to support such a small feature.
We can=E2=80=99t prove the implementation difficulty without trying to impl=
ement it. The proof (or disproof) is in the pudding.
> That said, it's true that we're slowly moving away from recursion as the =
be-all/end-all. C++11 variadic templates start to address some reasons we u=
se recursion so much, as do its restricted constexpr functions. C++14 std::=
index_sequence helps a bit (by at least hiding some kinds of recursion in a=
library class), and its generalized constexpr functions-help a lot (by mov=
ing more complex meta-computations to function rather than template code); =
C++17 fold expressions are another big step (by eliminating recursion entir=
ely from compatible kinds of computations). Most of those approaches don't =
eliminate the explosion of template helper functions, though (fold expressi=
ons being a massive exception to that claim).=20
>=20
> This proposal is just trying to eliminate a source of recursion and/or he=
lper functions that these previous advances don't seem to have covered. The=
main messiness that would be left is std::tuple and std::get, both of whic=
h seem pretty difficult to achieve non-recursively.
The proposal doesn=E2=80=99t eliminate any template recursion, it eliminate=
s [make_]index_sequence uses and attendant helper template declarations. Re=
cursion is needed for algorithms where each iteration depends on the last. =
index_sequence and your proposal are useful when each pack item is treated =
independently.
>> template < typename tuple_like >
>> int hash(tuple_like const &tup) {
>> return hash( ... ^ std::get< unpack_sequence( std::tuple_size< tuple_=
like >::value ) >( tup ) );
>> }
>=20
> In contrast, your unpack_sequence would have to "hoist" an otherwise non-=
pack statement, giving it a second set of variadic templates (the size_t...=
sequence).
unpack_sequence(N) would simply be an unexpanded pack (=C2=A714.5.3/6). =E2=
=80=9CHoisting=E2=80=9D is just what happens whenever you name a pack. The =
possibility of an unexpanded pack in a non-template context is also part of=
the price of N3728.
> N3728 would give something nearly identical. Both create a new parameter =
pack to be unpacked, in addition to any packs that were already present.
>=20
> On the other hand, these "create-a-pack" approaches have the benefit of *=
not* needing to explicitly bring in a <typename...> pack. That could be use=
ful at times, such as the tuple_like idiom you make a good argument for usi=
ng. Creating a pack also means the code won't care whether there are other =
packs around; nor would it care whether those other packs are type, non-typ=
e, or template template.=20
Right.
I see this as a dichotomy between two local optimums: If no new keyword is =
allowed, the best solution is indexed_type because it doesn=E2=80=99t care =
whether the pack is type or non-type, it only requires a type in a deduced =
pack pattern. It=E2=80=99s as close to a drop-in replacement as we can get.=
If a new keyword is allowed, the best solution is unpack_sequence because =
it allows you to locally unpack things (even numeric sequences with other p=
ack basis), without introducing any new kind of entity to the language.
Even if my sensibility about optimality is off, there are two mutually excl=
usive alternatives. I think the committee is willing to make a bigger chang=
e, so it=E2=80=99s not too much to worry about adding keyword or such.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_897D65A9-0CE8-49A0-9991-2FD2AE6E9B22
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9307=
=E2=80=9325, at 4:33 AM, Ryan Johnson <<a href=3D"mailto:scovich@gmail.c=
om" class=3D"">scovich@gmail.com</a>> wrote:</div><br class=3D"Apple-int=
erchange-newline"><div class=3D"">
=20
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
" class=3D"">
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<div class=3D"moz-cite-prefix">On 23/07/2015 9:06 PM, David Krauss
wrote:<br class=3D"">
</div>
<blockquote cite=3D"mid:E4E74785-CF93-4DB2-865A-0CC760F28519@gmail.com"=
type=3D"cite" class=3D"">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8" class=3D"">
<br class=3D"">
<div class=3D"">
<div class=3D"">What=E2=80=99s the default argument for?</div>
</div>
</blockquote>
A stand-in for the missing compiler magic. Makes N available without
the user having to specify it directly. Though I start to get the
impression you want the magic to happen directly in the
signature/declaration of foo, triggered by the compiler's
recognizing the (otherwise utterly mundane) std::indexed_type? </d=
iv></div></blockquote><div><br class=3D""></div><div>The magic would happen=
in a modification to the type <font face=3D"Courier" class=3D"">T</font> g=
enerated by <font face=3D"Courier" class=3D"">indexed_type<T></font>.=
In terms of the <font face=3D"Courier" class=3D"">[[__index]]</font> =
attribute:</div><div><br class=3D""></div><div><span style=3D"font-family: =
Courier;" class=3D"">// Standard library source code</span></div><div><span=
style=3D"font-family: Courier;" class=3D"">template< typename type >=
</span></div><div><span style=3D"font-family: Courier;" class=3D"">using in=
dexed_type =3D Ts [[__index (Xs)]];</span></div><div><span style=3D"font-fa=
mily: Courier;" class=3D""><br class=3D""></span></div><div><span style=3D"=
font-family: Courier;" class=3D"">// User source code</span></div><div><spa=
n style=3D"font-family: Courier;" class=3D"">template <typename ... Ts, =
std::size_t ... Xs></span><br class=3D"" style=3D"font-family: Courier;"=
><span style=3D"font-family: Courier;" class=3D"">std::vector<std::size_=
t> foo( std::indexed_type< Ts, Xs > && ...) { return {Xs..=
..}; }</span></div><div><span style=3D"font-family: Courier;" class=3D""><br=
class=3D""></span></div><div><span style=3D"font-family: Courier;" class=
=3D"">// After alias template substitution</span></div><div><span style=3D"=
font-family: Courier;" class=3D"">template <typename ... Ts, std::size_t=
... Xs></span><br class=3D"" style=3D"font-family: Courier;"><span styl=
e=3D"font-family: Courier;" class=3D"">std::vector<std::size_t> foo( =
Ts [[__index (Xs)]] && ...) { return {Xs...}; }</span><br class=3D"=
" style=3D"font-family: Courier;"></div><div><font face=3D"Courier" class=
=3D""> =
// ^ </font><span style=3D"font-family: Co=
urier;" class=3D"">both</span><span style=3D"font-family: Courier;" class=
=3D""> </span><span style=3D"font-family: Courier;" class=3D"">deduced=
^</span></div><div><br class=3D""></div><div>The implementation work would=
be in adding a new deduced context. (Again, the implementation would not l=
ikely use actual double-bracket attribute syntax, I=E2=80=99m just showing =
where such an internal keyword could fit in the grammar.)</div><div><br cla=
ss=3D""></div><div>You could say that <font face=3D"Courier" class=3D"">std=
::indexed_type</font> would generate a magic signature, but only by applyin=
g ordinary alias template substitution to a magic keyword.</div><br class=
=3D""><blockquote type=3D"cite" class=3D""><div bgcolor=3D"#FFFFFF" text=3D=
"#000000" class=3D"">If I understand correctly, you are proposing to make f=
oo() itself
magical, with the magic triggered by the appearance of an otherwise
mundane std::indexed_type in its signature, or by some variable
attribute affixed to the args. The problem is, the way template
deduction works in C++, the compiler will not even consider foo()
because the Xs cannot be deduced from information supplied *at the
call site* and so it will never see the bits that are supposed to
trigger the magic that would provide Xs. <br class=3D""></div></blockqu=
ote><div><br class=3D""></div><div>Parameters are deduced when they are men=
tioned in deduced contexts. If the compiler=E2=80=99s internals need an arg=
ument to correspond to the index sequence parameter, it can simply generate=
such a pack, upon encountering the magic keyword in the signature.</div><b=
r class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div bgco=
lor=3D"#FFFFFF" text=3D"#000000" class=3D"">Changing that behavior would be=
a Big Deal, because it changes the
semantics of template selection---which would already be a big deal
by itself---in a way that requires the compiler to do significantly
more work for all template candidates (searching for bits of magic
in their signatures), when the vast majority of them will not
actually make use of the feature. I doubt the Committee would be
interested in making such a large change to the language to support
such a small feature.<br class=3D""></div></div></blockquote><div><br c=
lass=3D""></div><div>We can=E2=80=99t prove the implementation difficulty w=
ithout trying to implement it. The proof (or disproof) is in the pudding.</=
div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><di=
v bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">That said, it's true that=
we're slowly moving away from recursion as
the be-all/end-all. C++11 variadic templates start to address some
reasons we use recursion so much, as do its restricted constexpr
functions. C++14 std::index_sequence helps a bit (by at least hiding
some kinds of recursion in a library class), and its generalized
constexpr functions-help a lot (by moving more complex
meta-computations to function rather than template code); C++17 fold
expressions are another big step (by eliminating recursion entirely
from compatible kinds of computations). Most of those approaches
don't eliminate the explosion of template helper functions, though
(fold expressions being a massive exception to that claim). <br class=
=3D"">
<br class=3D"">
This proposal is just trying to eliminate a source of recursion
and/or helper functions that these previous advances don't seem to
have covered. The main messiness that would be left is std::tuple
and std::get, both of which seem pretty difficult to achieve
non-recursively.<br class=3D""></div></div></blockquote><div><br class=
=3D""></div><div>The proposal doesn=E2=80=99t eliminate any template recurs=
ion, it eliminates [<font face=3D"Courier" class=3D"">make_</font>]<font fa=
ce=3D"Courier" class=3D"">index_sequence</font> uses and attendant helper t=
emplate declarations. Recursion is needed for algorithms where each iterati=
on depends on the last. <font face=3D"Courier" class=3D"">index_sequence</f=
ont> and your proposal are useful when each pack item is treated independen=
tly.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D=
""><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<blockquote type=3D"cite" class=3D""><font class=3D"" face=3D"Courier">=
template <
typename tuple_like ><br class=3D"">
int hash(tuple_like const &tup) {<br class=3D"">
return hash( ... ^ std::get< </font><span styl=
e=3D"font-family: Courier;" class=3D"">unpack_sequence</span><font class=3D=
"" face=3D"Courier">( std::tuple_size< tuple_like
>::value ) >( tup ) );<br class=3D"">
}</font></blockquote>
<br class=3D"">
In contrast, your unpack_sequence would have to "hoist" an otherwise
non-pack statement, giving it a second set of variadic templates
(the size_t... sequence). </div></div></blockquote><div><br class=3D"">=
</div><div><font face=3D"Courier" class=3D"">unpack_sequence(N)</font> woul=
d simply be an unexpanded pack (=C2=A714.5.3/6). =E2=80=9CHoisting=E2=80=9D=
is just what happens whenever you name a pack. The possibility of an unexp=
anded pack in a non-template context is also part of the price of N3728.</d=
iv><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div=
bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">N3728 would give something=
nearly
identical. Both create a new parameter pack to be unpacked, in
addition to any packs that were already present.<br class=3D"">
<br class=3D"">
On the other hand, these "create-a-pack" approaches have the benefit
of *not* needing to explicitly bring in a <typename...> pack.
That could be useful at times, such as the tuple_like idiom you make
a good argument for using. Creating a pack also means the code won't
care whether there are other packs around; nor would it care whether
those other packs are type, non-type, or template template. <br class=
=3D""></div></div></blockquote><br class=3D""></div><div>Right.</div><div><=
br class=3D""></div><div>I see this as a dichotomy between two local optimu=
ms: If no new keyword is allowed, the best solution is <font face=3D"Courie=
r" class=3D"">indexed_type</font> because it doesn=E2=80=99t care whether t=
he pack is type or non-type, it only requires a type in a deduced pack patt=
ern. It=E2=80=99s as close to a drop-in replacement as we can get. If a new=
keyword is allowed, the best solution is <font face=3D"Courier" class=3D""=
>unpack_sequence</font> because it allows you to locally unpack things (eve=
n numeric sequences with other pack basis), without introducing any new kin=
d of entity to the language.</div><div><br class=3D""></div><div>Even if my=
sensibility about optimality is off, there are two mutually exclusive alte=
rnatives. I think the committee is willing to make a bigger change, so it=
=E2=80=99s not too much to worry about adding keyword or such.</div><div><b=
r class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_897D65A9-0CE8-49A0-9991-2FD2AE6E9B22--
.
Author: David Krauss <potswa@gmail.com>
Date: Sat, 25 Jul 2015 10:55:18 +0800
Raw View
--Apple-Mail=_B86C29B1-3314-4CE6-AE7D-C7D43BF3ED6A
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9307=E2=80=9325, at 10:09 AM, David Krauss <potswa@gmail.co=
m> wrote:
>=20
> The magic would happen in a modification to the type T generated by index=
ed_type<T>. In terms of the [[__index]] attribute:
>=20
> // Standard library source code
> template< typename type >
> using indexed_type =3D Ts [[__index (Xs)]];
Sorry, that should be:
template< typename type, size_t index >
using indexed_type =3D type [[__index (index)]];
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_B86C29B1-3314-4CE6-AE7D-C7D43BF3ED6A
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9307=
=E2=80=9325, at 10:09 AM, David Krauss <<a href=3D"mailto:potswa@gmail.c=
om" class=3D"">potswa@gmail.com</a>> wrote:</div><br class=3D"Apple-inte=
rchange-newline"><div class=3D""><div style=3D"font-family: Helvetica; font=
-size: 12px; font-style: normal; font-variant: normal; font-weight: normal;=
letter-spacing: normal; line-height: normal; orphans: auto; text-align: st=
art; text-indent: 0px; text-transform: none; white-space: normal; widows: a=
uto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D"">The mag=
ic would happen in a modification to the type<span class=3D"Apple-converted=
-space"> </span><font face=3D"Courier" class=3D"">T</font><span class=
=3D"Apple-converted-space"> </span>generated by<span class=3D"Apple-co=
nverted-space"> </span><font face=3D"Courier" class=3D"">indexed_type&=
lt;T></font>. In terms of the <font face=3D"Courier" class=3D"">[[_=
_index]]</font><span class=3D"Apple-converted-space"> </span>attribute=
:</div><div style=3D"font-family: Helvetica; font-size: 12px; font-style: n=
ormal; font-variant: normal; font-weight: normal; letter-spacing: normal; l=
ine-height: normal; orphans: auto; text-align: start; text-indent: 0px; tex=
t-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -w=
ebkit-text-stroke-width: 0px;" class=3D""><br class=3D""></div><div style=
=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-varia=
nt: normal; font-weight: normal; letter-spacing: normal; line-height: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px;" class=3D""><span class=3D"" style=3D"font-family: Courier;">/=
/ Standard library source code</span></div><div style=3D"font-family: Helve=
tica; font-size: 12px; font-style: normal; font-variant: normal; font-weigh=
t: normal; letter-spacing: normal; line-height: normal; orphans: auto; text=
-align: start; text-indent: 0px; text-transform: none; white-space: normal;=
widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=3D=
""><span class=3D"" style=3D"font-family: Courier;">template< typename t=
ype ></span></div><div style=3D"font-family: Helvetica; font-size: 12px;=
font-style: normal; font-variant: normal; font-weight: normal; letter-spac=
ing: normal; line-height: normal; orphans: auto; text-align: start; text-in=
dent: 0px; text-transform: none; white-space: normal; widows: auto; word-sp=
acing: 0px; -webkit-text-stroke-width: 0px;" class=3D""><span class=3D"" st=
yle=3D"font-family: Courier;">using indexed_type =3D Ts [[__index (Xs)]];</=
span></div></div></blockquote><br class=3D""></div><div>Sorry, that should =
be:</div><div><br class=3D""></div><font face=3D"Courier" class=3D"">templa=
te< typename type, size_t index ><br class=3D"">using indexed_type =
=3D type [[__index (index)]];<br class=3D""></font><br class=3D""></body></=
html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_B86C29B1-3314-4CE6-AE7D-C7D43BF3ED6A--
.
Author: Myriachan <myriachan@gmail.com>
Date: Fri, 24 Jul 2015 20:49:29 -0700 (PDT)
Raw View
------=_Part_1328_1662627215.1437796169249
Content-Type: multipart/alternative;
boundary="----=_Part_1329_367892344.1437796169250"
------=_Part_1329_367892344.1437796169250
Content-Type: text/plain; charset=UTF-8
What if there were a keyword "restof...(Xs)" (not real name) that returned
a template parameter pack of everything after the currently-expanding one?
This would work and even be more flexible than an "indexof...(Xs)" operator.
void test_function(const std::tuple<int, int, int> &, const std::tuple<int,
int> &, const std::tuple<int> &)
{
std::puts("meow");
}
template <typename... Ts>
void intermediate_function()
{
test_function(std::tuple<Ts, restof...(Ts)>()...);
}
void caller_function()
{
intermediate_function<int, int, int>();
}
Then the example from the beginning of the thread becomes:
template <typename...Ts>
std::vector<std::size_t> foo(Ts&& ...) { return {sizeof...(Ts) - sizeof...(
restof...(Ts)) - 1}; }
int main() {
std::vector a{0,1,2}, b=foo("hi", "ho", "hum");
assert(a == b); // succeeds
}
Melissa
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1329_367892344.1437796169250
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div style=3D"word-wrap:break-word">What if there were a k=
eyword "<span style=3D"font-family: courier new,monospace;">restof...(=
Xs)</span>" (not real name) that returned a template parameter pack of=
everything after the currently-expanding one?=C2=A0 This would work and ev=
en be more flexible than an "<span style=3D"font-family: courier new,m=
onospace;">indexof...(Xs)</span>" operator.<br><br><div class=3D"prett=
yprint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(18=
7, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-word=
;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D=
"color: #008;" class=3D"styled-by-prettify">void</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> test_function</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">const</span><span style=3D"color: #000;" c=
lass=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">tuple</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify"><</span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">int</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">int</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;"=
class=3D"styled-by-prettify">int</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">></span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">&,</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">cons=
t</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">tuple</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">int</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">int</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">></span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> </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">const</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> std</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">tuple</span><span style=3D"color: #0=
80;" class=3D"styled-by-prettify"><int></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: #000;" class=
=3D"styled-by-prettify"><br></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>=C2=A0 =C2=A0 std</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">puts</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">(</span><span style=3D"color: #080;" class=3D"styled-by-prettify">&qu=
ot;meow"</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><sp=
an 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 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">typename</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">...</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"st=
yled-by-prettify">Ts</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">></span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">vo=
id</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> interme=
diate_function</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 t=
est_function</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">tuple</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"c=
olor: #606;" class=3D"styled-by-prettify">Ts</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> restof</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">...(</span><span style=3D"color: #606;" class=3D"st=
yled-by-prettify">Ts</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">)>()...);</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><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=
><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">void<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> caller_fun=
ction</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 intermedia=
te_function</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
><</span><span style=3D"color: #008;" class=3D"styled-by-prettify">int</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"col=
or: #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">int</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">>();</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></div></code></div><br><br><br>Then the example from the be=
ginning of the thread becomes:<br><br><div class=3D"prettyprint" style=3D"b=
ackground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); bord=
er-style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"=
prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">template</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"style=
d-by-prettify"><</span><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">typename</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">...</span><span style=3D"color: #606;" class=3D"styled-by-prettify">=
Ts</span><span style=3D"color: #660;" class=3D"styled-by-prettify">></sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>std</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify">vector</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">std</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify">size_t</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">></span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> foo</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">(</span><span style=3D"color: #606;" class=3D"styled-by-prettif=
y">Ts</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&=
&</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">...)</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </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;" 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-pre=
ttify">sizeof</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">...(</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Ts<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #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">sizeof</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">...(</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">restof</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">...(</span><span style=3D"color: #606;" class=3D"styled-by-p=
rettify">Ts</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 st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #066;" class=3D"styled-by-prettify">1</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"style=
d-by-prettify">}</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br><br></span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> ma=
in</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0std</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">vector a</span><span style=3D"co=
lor: #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: #066;" class=3D"style=
d-by-prettify">1</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">,</span><span style=3D"color: #066;" class=3D"styled-by-prettify">2</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">},</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> b</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">foo</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #080;" class=
=3D"styled-by-prettify">"hi"</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #080;" class=3D"styled-by-=
prettify">"ho"</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #080;" class=3D"styled-by-prettify">&quo=
t;hum"</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>);</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=
=A0 =C2=A0</span><span style=3D"color: #008;" class=3D"styled-by-prettify">=
assert</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify">a </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">=3D=3D</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> b</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" clas=
s=3D"styled-by-prettify">// succeeds</span><span style=3D"color: #000;" cla=
ss=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></div></code></div><br><br>Melissa<br><br></div></div=
>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1329_367892344.1437796169250--
------=_Part_1328_1662627215.1437796169249--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Sat, 25 Jul 2015 06:40:05 -0600
Raw View
This is a multi-part message in MIME format.
--------------030006080908060009070705
Content-Type: text/plain; charset=UTF-8; format=flowed
On 24/07/2015 9:49 PM, Myriachan wrote:
> What if there were a keyword "restof...(Xs)" (not real name) that
> returned a template parameter pack of everything after the
> currently-expanding one?
Interesting... kind of a lispy car/cdr for parameter packs?
> This would work and even be more flexible than an "indexof...(Xs)"
> operator.
>
> |
> voidtest_function(conststd::tuple<int,int,int>&,conststd::tuple<int,int>&,conststd::tuple<int>&)
> {
> std::puts("meow");
> }
>
> template<typename...Ts>
> voidintermediate_function()
> {
> test_function(std::tuple<Ts,restof...(Ts)>()...);
> }
>
> voidcaller_function()
> {
> intermediate_function<int,int,int>();
> }
> |
This one can be achieved already, simply by having `template <typename
T, typename... Ts>', and is
often used to require 1+ parameters rather than the 0+ a parameter pack
allows.
> Then the example from the beginning of the thread becomes:
>
> |
> template<typename...Ts>
> std::vector<std::size_t>foo(Ts&&...){return{sizeof...(Ts)-sizeof...(restof...(Ts))-1};}
>
> |
|
Something is off with this example; a missing "..." perhaps?|
|
|template<typename...Ts>
std::vector<std::size_t>foo(Ts&&...)
{
return{(sizeof...(Ts)-sizeof...(restof...(Ts))-1)...};
}
|
|
That's actually rather clever.
I feel like this would be a nice addition to N3728. Once you have
first-class parameter packs, having the ability to slice and dice them
would be very useful, and pack manipulation operations are notably
absent from that proposal.
I'm not so sure it makes a good stand-alone feature, though, because C++
currently has no concept of manipulating parameter packs inside a function.
Ryan
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--------------030006080908060009070705
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 24/07/2015 9:49 PM, Myriachan wrote:<=
br>
</div>
<blockquote
cite=3D"mid:cf74f255-1389-4206-940c-12bd81b4f65e@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div style=3D"word-wrap:break-word">What if there were a keyword "<=
span
style=3D"font-family: courier new,monospace;">restof...(Xs)</sp=
an>"
(not real name) that returned a template parameter pack of
everything after the currently-expanding one?=C2=A0 </div>
</div>
</blockquote>
Interesting... kind of a lispy car/cdr for parameter packs?<br>
<br>
<blockquote
cite=3D"mid:cf74f255-1389-4206-940c-12bd81b4f65e@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div style=3D"word-wrap:break-word">This would work and even be
more flexible than an "<span style=3D"font-family: courier
new,monospace;">indexof...(Xs)</span>" operator.<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;"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span style=3D"color: #008;"
class=3D"styled-by-prettify">void</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
test_function</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">(</span><span style=3D"color=
:
#008;" class=3D"styled-by-prettify">const</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> std<=
/span><span
style=3D"color: #660;" class=3D"styled-by-prettify">::</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify">tuple=
</span><span
style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span><span
style=3D"color: #008;" class=3D"styled-by-prettify">int</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">int</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">int</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">><=
/span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">&=
,</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">const=
</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> std<=
/span><span
style=3D"color: #660;" class=3D"styled-by-prettify">::</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify">tuple=
</span><span
style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span><span
style=3D"color: #008;" class=3D"styled-by-prettify">int</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">int</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">><=
/span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">&=
,</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">const=
</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> std<=
/span><span
style=3D"color: #660;" class=3D"styled-by-prettify">::</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify">tuple=
</span><span
style=3D"color: #080;" class=3D"styled-by-prettify"><i=
nt></span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><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>
=C2=A0 =C2=A0 std</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">::</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">puts<=
/span><span
style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
style=3D"color: #080;" class=3D"styled-by-prettify">"meow=
"</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">);</s=
pan><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: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span><span
style=3D"color: #008;" class=3D"styled-by-prettify">typen=
ame</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">...</=
span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #606;" class=3D"styled-by-prettify">Ts</s=
pan><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">void</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
intermediate_function</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>
=C2=A0 =C2=A0 test_function</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">::</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify">tuple=
</span><span
style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span><span
style=3D"color: #606;" class=3D"styled-by-prettify">Ts</s=
pan><span
style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify">
restof</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">...(</span><span
style=3D"color: #606;" class=3D"styled-by-prettify">Ts</s=
pan><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">void</span><span
style=3D"color: #000;" class=3D"styled-by-prettify">
caller_function</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>
=C2=A0 =C2=A0 intermediate_function</span><span style=3D"=
color:
#660;" class=3D"styled-by-prettify"><</span><span
style=3D"color: #008;" class=3D"styled-by-prettify">int</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">int</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">int</=
span><span
style=3D"color: #660;" class=3D"styled-by-prettify">>(=
);</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
</span><span style=3D"color: #660;"
class=3D"styled-by-prettify">}</span></div>
</code></div>
</div>
</div>
</blockquote>
This one can be achieved already, simply by having `template
<typename T, typename... Ts>', and is <br>
often used to require 1+ parameters rather than the 0+ a parameter
pack allows. <br>
<br>
<blockquote
cite=3D"mid:cf74f255-1389-4206-940c-12bd81b4f65e@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">
<div style=3D"word-wrap:break-word">Then the example from the
beginning of the thread becomes:<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;"><code
class=3D"prettyprint">
<div class=3D"subprettyprint"><span style=3D"color: #008;"
class=3D"styled-by-prettify">template</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span><span
style=3D"color: #008;" class=3D"styled-by-prettify">typen=
ame</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">...</=
span><span
style=3D"color: #606;" class=3D"styled-by-prettify">Ts</s=
pan><span
style=3D"color: #660;" class=3D"styled-by-prettify">><=
/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">vecto=
r</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">::</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify">size_=
t</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">><=
/span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> foo<=
/span><span
style=3D"color: #660;" class=3D"styled-by-prettify">(</sp=
an><span
style=3D"color: #606;" class=3D"styled-by-prettify">Ts</s=
pan><span
style=3D"color: #660;" class=3D"styled-by-prettify">&=
&</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">...)<=
/span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">retur=
n</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">{</sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">sizeo=
f</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">...(<=
/span><span
style=3D"color: #606;" class=3D"styled-by-prettify">Ts</s=
pan><span
style=3D"color: #660;" class=3D"styled-by-prettify">)</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">-</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #008;" class=3D"styled-by-prettify">sizeo=
f</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">...(<=
/span><span
style=3D"color: #000;" class=3D"styled-by-prettify">resto=
f</span><span
style=3D"color: #660;" class=3D"styled-by-prettify">...(<=
/span><span
style=3D"color: #606;" class=3D"styled-by-prettify">Ts</s=
pan><span
style=3D"color: #660;" class=3D"styled-by-prettify">))</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">-</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #066;" class=3D"styled-by-prettify">1</sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">};</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span
style=3D"color: #660;" class=3D"styled-by-prettify">}</sp=
an><span
style=3D"color: #000;" class=3D"styled-by-prettify"><br>
<br>
</span></div>
</code></div>
</div>
</div>
</blockquote>
<code><br>
Something is off with this example; a missing "..." perhaps?</code><b=
r>
<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"prettyprint">
<div class=3D"subprettyprint"><code class=3D"prettyprint"><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"><</spa=
n><span
style=3D"color: #008;" class=3D"styled-by-prettify">typename<=
/span><span
style=3D"color: #660;" class=3D"styled-by-prettify">...</span=
><span
style=3D"color: #606;" class=3D"styled-by-prettify">Ts</span>=
<span
style=3D"color: #660;" class=3D"styled-by-prettify">></spa=
n><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">vector</span><span
style=3D"color: #660;" class=3D"styled-by-prettify"><</spa=
n><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"styled-by-prettify">size_t</s=
pan><span
style=3D"color: #660;" class=3D"styled-by-prettify">></spa=
n><span
style=3D"color: #000;" class=3D"styled-by-prettify"> foo</spa=
n><span
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><=
span
style=3D"color: #606;" class=3D"styled-by-prettify">Ts</span>=
<span
style=3D"color: #660;" class=3D"styled-by-prettify">&&=
;</span><span
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span
style=3D"color: #660;" class=3D"styled-by-prettify">...)</spa=
n><span
style=3D"color: #000;" class=3D"styled-by-prettify"></span><s=
pan
style=3D"color: #660;" class=3D"styled-by-prettify"><br>
{</span><span style=3D"color: #000;"
class=3D"styled-by-prettify"> </span><span style=3D"color:
#008;" class=3D"styled-by-prettify"><br>
=C2=A0=C2=A0 return</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">sizeof</s=
pan><span
style=3D"color: #660;" class=3D"styled-by-prettify">...(</spa=
n><span
style=3D"color: #606;" class=3D"styled-by-prettify">Ts</span>=
<span
style=3D"color: #660;" class=3D"styled-by-prettify">)</span><=
span
style=3D"color: #000;" class=3D"styled-by-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"styled-by-prettify">sizeof</s=
pan><span
style=3D"color: #660;" class=3D"styled-by-prettify">...(</spa=
n><span
style=3D"color: #000;" class=3D"styled-by-prettify">restof</s=
pan><span
style=3D"color: #660;" class=3D"styled-by-prettify">...(</spa=
n><span
style=3D"color: #606;" class=3D"styled-by-prettify">Ts</span>=
<span
style=3D"color: #660;" class=3D"styled-by-prettify">))</span>=
<span
style=3D"color: #000;" class=3D"styled-by-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: #066;" class=3D"styled-by-prettify">1</span><=
span
style=3D"color: #660;" class=3D"styled-by-prettify">)...};</s=
pan><span
style=3D"color: #000;" class=3D"styled-by-prettify"></span><s=
pan
style=3D"color: #660;" class=3D"styled-by-prettify"><br>
}</span><span style=3D"color: #000;"
class=3D"styled-by-prettify"><br>
</span></code><span style=3D"color: #000;"
class=3D"styled-by-prettify"></span></div>
</code></div>
<br>
That's actually rather clever.<br>
<br>
I feel like this would be a nice addition to N3728. Once you have
first-class parameter packs, having the ability to slice and dice
them would be very useful, and pack manipulation operations are
notably absent from that proposal. <br>
<br>
I'm not so sure it makes a good stand-alone feature, though, because
C++ currently has no concept of manipulating parameter packs inside
a function.<br>
<br>
Ryan<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------030006080908060009070705--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Sat, 25 Jul 2015 09:18:54 -0600
Raw View
This is a multi-part message in MIME format.
--------------060905070502070200090002
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 24/07/2015 8:09 PM, David Krauss wrote:
>
>> On 2015=E2=80=9307=E2=80=9325, at 4:33 AM, Ryan Johnson <scovich@gmail.c=
om=20
>> <mailto:scovich@gmail.com>> wrote:
>>
>> On 23/07/2015 9:06 PM, David Krauss wrote:
>>>
>>> What=E2=80=99s the default argument for?
>> A stand-in for the missing compiler magic. Makes N available without=20
>> the user having to specify it directly. Though I start to get the=20
>> impression you want the magic to happen directly in the=20
>> signature/declaration of foo, triggered by the compiler's recognizing=20
>> the (otherwise utterly mundane) std::indexed_type?
>
> The magic would happen in a modification to the type T generated by=20
> indexed_type<T>. In terms of the [[__index]] attribute:
>
> // Standard library source code
> template< typename type >
> using indexed_type =3D Ts [[__index (Xs)]];
>
> // User source code
> template <typename ... Ts, std::size_t ... Xs>
> std::vector<std::size_t> foo( std::indexed_type< Ts, Xs > && ...) {=20
> return {Xs...}; }
>
> // After alias template substitution
> template <typename ... Ts, std::size_t ... Xs>
> std::vector<std::size_t> foo( Ts [[__index (Xs)]] && ...) { return=20
> {Xs...}; }
> // ^ bothdeduced ^
>
> The implementation work would be in adding a new deduced context.=20
> (Again, the implementation would not likely use actual double-bracket=20
> attribute syntax, I=E2=80=99m just showing where such an internal keyword=
=20
> could fit in the grammar.)
>
> You could say that std::indexed_type would generate a magic signature,=20
> but only by applying ordinary alias template substitution to a magic=20
> keyword.
OK, that's about what I thought you were saying.
>
>> If I understand correctly, you are proposing to make foo() itself=20
>> magical, with the magic triggered by the appearance of an otherwise=20
>> mundane std::indexed_type in its signature, or by some variable=20
>> attribute affixed to the args. The problem is, the way template=20
>> deduction works in C++, the compiler will not even consider foo()=20
>> because the Xs cannot be deduced from information supplied *at the=20
>> call site* and so it will never see the bits that are supposed to=20
>> trigger the magic that would provide Xs.
>
> Parameters are deduced when they are mentioned in deduced contexts. If=20
> the compiler=E2=80=99s internals need an argument to correspond to the in=
dex=20
> sequence parameter, it can simply generate such a pack, upon=20
> encountering the magic keyword in the signature.
From that perspective, the `Ts [[__index (Xs)]]' is vastly more likely=20
to be implementable, because the compiler (clang at least) has no=20
machinery in place to detect "special" template class names (which could=20
be obfuscated arbitrarily by use of typedefs, aliases, etc.). Putting=20
the magic in an attribute also solves the namespace pollution problem an=20
operator would face.
However... I just realized there's a glaring problem with this approach:=20
it does not work with member functions of a template class. To give a=20
simplistic example:
template <typename... Ts>
struct my_tuple : std::tuple<Ts...>
{
using std::tuple<Ts...>::tuple;
int hash()
{
/* Nothing to attach [[__index(Xs)]] to, nor std::indexed_type */
}
};
There's no clear way to make my_tuple::hash() a template function in a=20
way that allowed the necessary Ts,Xs pairing, because doing so would=20
create a new/different typed parameter pack and hash() doesn't take any=20
arguments to kick-start deduction with. It also wouldn't work to require=20
the Xs... at class level, because that would force the user to supply=20
all the Xs when instantiating the class. You couldn't hide the extra=20
template parameters behind an alias template, because those suffer the=20
same shortcoming.
The __indexof operator doesn't suffer this problem because it can work=20
directly with the existing parameter pack, rather than having to=20
manufacture its own "special" one.
Based on that, I'd say both the std::indexed_type<Ts,Xs> and Ts=20
[[__index(Xs)]] ideas are out of the running.
>> Changing that behavior would be a Big Deal, because it changes the=20
>> semantics of template selection---which would already be a big deal=20
>> by itself---in a way that requires the compiler to do significantly=20
>> more work for all template candidates (searching for bits of magic in=20
>> their signatures), when the vast majority of them will not actually=20
>> make use of the feature. I doubt the Committee would be interested in=20
>> making such a large change to the language to support such a small=20
>> feature.
>
> We can=E2=80=99t prove the implementation difficulty without trying to=20
> implement it. The proof (or disproof) is in the pudding.
Potentially fatal flaws aside, I've spent a bit of time around the=20
relevant parts of clang's implementation, while implementing the=20
__indexof operator.
I think I know enough that I could attempt a prototype of the Ts=20
[[pack_index(Xs)]] attribute approach to see whether it's easy or even=20
possible to generate the extra parameter Xs parameter pack at the right=20
moment.
The std::indexed_type<Ts,Xs> flavor of magic would be a non-starter,=20
though, because there is no machinery in place to detect a "special"=20
template class name (which could be obfuscated arbitrarily by use of=20
typedefs and template aliases).
All Standards-mandated template classes are implemented either without=20
magic, or by invoking magical built-in operators as part of their=20
(otherwise mundane) definition. Everything I've seen of gcc's=20
libstdc++-v3 says the same approach is used there. No doubt the=20
functionality could be jammed in by someone with enough motivation, but=20
my impression is that it wouldn't be a pleasant task, and I definitely=20
don't know enough about clang to attempt it myself.
>> This proposal is just trying to eliminate a source of recursion=20
>> and/or helper functions that these previous advances don't seem to=20
>> have covered. The main messiness that would be left is std::tuple and=20
>> std::get, both of which seem pretty difficult to achieve non-recursively=
..
>
> The proposal doesn=E2=80=99t eliminate any template recursion, it elimina=
tes=20
> [make_]index_sequence uses and attendant helper template declarations.
Using std::make_index_sequence just moves the recursion from the call=20
site into library code, which changes nothing from the compiler's=20
perspective (see below). That's what I meant when I described it as=20
"hiding some kinds of recursion in a library class."
In libstdc++v3 (gcc) the recursion lurks in this helper template:
template<size_t _Num>
struct _Build_index_tuple
{
typedef typename _Build_index_tuple<_Num - 1>::__type::__next __type=
;
};
template<>
struct _Build_index_tuple<0>
{
typedef _Index_tuple<> __type;
};
In libc++ (clang), things are a *lot* more complex. It does 8x unwinding=20
of the recursion by means of helper template structs __make, __repeat,=20
__parity (an effort to improve compilation speed I imagine). The actual=20
recursion comes because the definitions of __make and __parity mutually=20
depend on each other. You can search for "struct __parity" in the source=20
browser <http://llvm.org/svn/llvm-project/libcxx/trunk/include/utility>=20
if you're interested in the gory details.
If you want to get rid of the recursion entirely, you have to either=20
eliminate the need for std::make_index_sequence (e.g. by introducing the=20
sort of feature this proposal focuses on), or else implement it=20
non-recursively (again, using the sort of feature this proposal focuses=20
on). I'd strongly prefer the former because it eliminates the=20
boilerplate that users have to deal with when using std::index_sequence.
>>> template < typename tuple_like >
>>> int hash(tuple_like const &tup) {
>>> return hash( ... ^ std::get< unpack_sequence( std::tuple_size<=20
>>> tuple_like >::value ) >( tup ) );
>>> }
>>
>> In contrast, your unpack_sequence would have to "hoist" an otherwise=20
>> non-pack statement, giving it a second set of variadic templates (the=20
>> size_t... sequence).
>
> unpack_sequence(N) would simply be an unexpanded pack (=C2=A714.5.3/6).=
=20
> =E2=80=9CHoisting=E2=80=9D is just what happens whenever you name a pack.=
The=20
> possibility of an unexpanded pack in a non-template context is also=20
> part of the price of N3728.
By "hoisting" I meant the use of an unexpanded parameter pack in a=20
context where one is not otherwise expected (thank you for helping me=20
nail that down with your concise statement). IMO that capability is the=20
main feature of N3728. Without the first-class parameter packs that=20
N3728 proposes, the notion of an unexpanded parameter pack outside any=20
variadic template context---or inside a variadic template context, but=20
in an expression that does not mention any of the formal parameter=20
packs---is completely foreign.
BTW, even if something like N3728 were accepted, it does not provide a=20
clean mechanism for converting a parameter pack into a <size_t...> pack,=20
so this proposal would still be useful. It does close an important gap,=20
though, by providing a way to define std::tuple non-recursively.
>> N3728 would give something nearly identical. Both create a new=20
>> parameter pack to be unpacked, in addition to any packs that were=20
>> already present.
>>
>> On the other hand, these "create-a-pack" approaches have the benefit=20
>> of *not* needing to explicitly bring in a <typename...> pack. That=20
>> could be useful at times, such as the tuple_like idiom you make a=20
>> good argument for using. Creating a pack also means the code won't=20
>> care whether there are other packs around; nor would it care whether=20
>> those other packs are type, non-type, or template template.
>
> Right.
>
> I see this as a dichotomy between two local optimums: If no new=20
> keyword is allowed, the best solution is indexed_type because it=20
> doesn=E2=80=99t care whether the pack is type or non-type, it only requir=
es a=20
> type in a deduced pack pattern.
I'm not seeing how you could use indexed_type with non-type or template=20
template parameter packs. If you still want to pursue it in spite of the=20
flaws discussed earlier, could you provide an example?
> If a new keyword is allowed, the best solution is unpack_sequence=20
> because it allows you to locally unpack things (even numeric sequences=20
> with other pack basis), without introducing any new kind of entity to=20
> the language.
Eh? It does require a new entity: an unexpanded parameter pack that is=20
not part of any enclosing variadic template definition. While it might=20
be tempting to hack it in quietly for this one (very limited) use case,=20
I suspect the Committee would much rather that any new entity be fleshed=20
out fully to avoid surprises and ugliness later on, when people=20
inevitably try to apply the concept in new and unanticipated ways.
That said, the unpack_sequence idea *is* tempting because it lets you=20
work with subsequences, an ability that __indexof() operator would not=20
provide. But I also feel like ability to slice and dice parameter packs=20
would be better integrated with N3728 or proposed as a separate feature=20
(which would fill the one remaining gap when working with tuples, namely=20
how to implement things like std::get and std::tuple_element=20
non-recursively).
Ryan
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------060905070502070200090002
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 24/07/2015 8:09 PM, David Krauss
wrote:<br>
</div>
<blockquote
cite=3D"mid:FBD72BF1-5E44-4B4E-90EA-3F726445819F@gmail.com"
type=3D"cite">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8">
<br class=3D"">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">On 2015=E2=80=9307=E2=80=9325, at 4:33 AM, Ryan J=
ohnson <<a
moz-do-not-send=3D"true" href=3D"mailto:scovich@gmail.com"
class=3D"">scovich@gmail.com</a>> wrote:</div>
<br class=3D"Apple-interchange-newline">
<div class=3D"">
<meta content=3D"text/html; charset=3Dutf-8"
http-equiv=3D"Content-Type" class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<div class=3D"moz-cite-prefix">On 23/07/2015 9:06 PM, David
Krauss wrote:<br class=3D"">
</div>
<blockquote
cite=3D"mid:E4E74785-CF93-4DB2-865A-0CC760F28519@gmail.com"
type=3D"cite" class=3D"">
<meta http-equiv=3D"Content-Type" content=3D"text/html;
charset=3Dutf-8" class=3D"">
<br class=3D"">
<div class=3D"">
<div class=3D"">What=E2=80=99s the default argument for?<=
/div>
</div>
</blockquote>
A stand-in for the missing compiler magic. Makes N
available without the user having to specify it directly.
Though I start to get the impression you want the magic to
happen directly in the signature/declaration of foo,
triggered by the compiler's recognizing the (otherwise
utterly mundane) std::indexed_type?=C2=A0</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>The magic would happen in a modification to the type <font
class=3D"" face=3D"Courier">T</font> generated by <font
class=3D"" face=3D"Courier">indexed_type<T></font>. In
terms of the=C2=A0<font class=3D"" face=3D"Courier">[[__index]]</=
font>
attribute:</div>
<div><br class=3D"">
</div>
<div><span style=3D"font-family: Courier;" class=3D"">// Standard
library source code</span></div>
<div><span style=3D"font-family: Courier;" class=3D"">template<
typename type ></span></div>
<div><span style=3D"font-family: Courier;" class=3D"">using
indexed_type =3D Ts [[__index (Xs)]];</span></div>
<div><span style=3D"font-family: Courier;" class=3D""><br class=3D"=
">
</span></div>
<div><span style=3D"font-family: Courier;" class=3D"">// User sourc=
e
code</span></div>
<div><span style=3D"font-family: Courier;" class=3D"">template
<typename ... Ts, std::size_t ... Xs></span><br
class=3D"" style=3D"font-family: Courier;">
<span style=3D"font-family: Courier;" class=3D"">std::vector<s=
td::size_t>
foo( std::indexed_type< Ts, Xs > && ...) {
return {Xs...}; }</span></div>
<div><span style=3D"font-family: Courier;" class=3D""><br class=3D"=
">
</span></div>
<div><span style=3D"font-family: Courier;" class=3D"">// After alia=
s
template substitution</span></div>
<div><span style=3D"font-family: Courier;" class=3D"">template
<typename ... Ts, std::size_t ... Xs></span><br
class=3D"" style=3D"font-family: Courier;">
<span style=3D"font-family: Courier;" class=3D"">std::vector<s=
td::size_t>
foo( Ts [[__index (Xs)]] && ...) { return {Xs...}; }</s=
pan><br
class=3D"" style=3D"font-family: Courier;">
</div>
<div><font class=3D"" face=3D"Courier">=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0//
^=C2=A0</font><span style=3D"font-family: Courier;" class=3D"">=
both</span><span
style=3D"font-family: Courier;" class=3D"">=C2=A0</span><span
style=3D"font-family: Courier;" class=3D"">deduced ^</span></di=
v>
<div><br class=3D"">
</div>
<div>The implementation work would be in adding a new deduced
context. (Again, the implementation would not likely use
actual double-bracket attribute syntax, I=E2=80=99m just showing =
where
such an internal keyword could fit in the grammar.)</div>
<div><br class=3D"">
</div>
<div>You could say that <font class=3D"" face=3D"Courier">std::inde=
xed_type</font>
would generate a magic signature, but only by applying
ordinary alias template substitution to a magic keyword.</div>
</div>
</blockquote>
OK, that's about what I thought you were saying.<br>
<br>
<blockquote
cite=3D"mid:FBD72BF1-5E44-4B4E-90EA-3F726445819F@gmail.com"
type=3D"cite">
<div><br class=3D"">
<blockquote type=3D"cite" class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">If I underst=
and
correctly, you are proposing to make foo() itself magical,
with the magic triggered by the appearance of an otherwise
mundane std::indexed_type in its signature, or by some
variable attribute affixed to the args. The problem is, the
way template deduction works in C++, the compiler will not
even consider foo() because the Xs cannot be deduced from
information supplied *at the call site* and so it will never
see the bits that are supposed to trigger the magic that
would provide Xs. <br class=3D"">
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>Parameters are deduced when they are mentioned in deduced
contexts. If the compiler=E2=80=99s internals need an argument to
correspond to the index sequence parameter, it can simply
generate such a pack, upon encountering the magic keyword in
the signature.</div>
</div>
</blockquote>
<br>
From that perspective, the `Ts [[__index (Xs)]]' is vastly more
likely to be implementable, because the compiler (clang at least)
has no machinery in place to detect "special" template class names
(which could be obfuscated arbitrarily by use of typedefs, aliases,
etc.). Putting the magic in an attribute also solves the namespace
pollution problem an operator would face. <br>
<br>
However... I just realized there's a glaring problem with this
approach: it does not work with member functions of a template
class. To give a simplistic example:<br>
<br>
template <typename... Ts><br>
struct my_tuple : std::tuple<Ts...><br>
{<br>
=C2=A0=C2=A0 using std::tuple<Ts...>::tuple;<br>
=C2=A0=C2=A0 int hash()<br>
=C2=A0=C2=A0 {<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Nothing to attach [[__index(Xs)]] to,=
nor std::indexed_type
*/<br>
=C2=A0=C2=A0 }<br>
};<br>
<br>
There's no clear way to make my_tuple::hash() a template function in
a way that allowed the necessary Ts,Xs pairing, because doing so
would create a new/different typed parameter pack and hash() doesn't
take any arguments to kick-start deduction with. It also wouldn't
work to require the Xs... at class level, because that would force
the user to supply all the Xs when instantiating the class. You
couldn't hide the extra template parameters behind an alias
template, because those suffer the same shortcoming.<br>
<br>
The __indexof operator doesn't suffer this problem because it can
work directly with the existing parameter pack, rather than having
to manufacture its own "special" one.<br>
=C2=A0=C2=A0 <br>
Based on that, I'd say both the std::indexed_type<Ts,Xs> and
Ts [[__index(Xs)]] ideas are out of the running. <br>
<br class=3D"">
<blockquote
cite=3D"mid:FBD72BF1-5E44-4B4E-90EA-3F726445819F@gmail.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">Changing t=
hat
behavior would be a Big Deal, because it changes the
semantics of template selection---which would already be a
big deal by itself---in a way that requires the compiler
to do significantly more work for all template candidates
(searching for bits of magic in their signatures), when
the vast majority of them will not actually make use of
the feature. I doubt the Committee would be interested in
making such a large change to the language to support such
a small feature.<br class=3D"">
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>We can=E2=80=99t prove the implementation difficulty without t=
rying
to implement it. The proof (or disproof) is in the pudding.</div>
</div>
</blockquote>
Potentially fatal flaws aside, I've spent a bit of time around the
relevant parts of clang's implementation, while implementing the
__indexof operator. <br>
<br>
I think I know enough that I could attempt a prototype of the Ts
[[pack_index(Xs)]] attribute approach to see whether it's easy or
even possible to generate the extra parameter Xs parameter pack at
the right moment.<br>
<br>
The std::indexed_type<Ts,Xs> flavor of magic would be a
non-starter, though, because there is no machinery in place to
detect a "special" template class name (which could be obfuscated
arbitrarily by use of typedefs and template aliases). <br>
<br>
All Standards-mandated template classes are implemented either
without magic, or by invoking magical built-in operators as part of
their (otherwise mundane) definition. Everything I've seen of gcc's
libstdc++-v3 says the same approach is used there. No doubt the
functionality could be jammed in by someone with enough motivation,
but my impression is that it wouldn't be a pleasant task, and I
definitely don't know enough about clang to attempt it myself.<br>
<br class=3D"">
<blockquote
cite=3D"mid:FBD72BF1-5E44-4B4E-90EA-3F726445819F@gmail.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D""> This
proposal is just trying to eliminate a source of recursion
and/or helper functions that these previous advances don't
seem to have covered. The main messiness that would be
left is std::tuple and std::get, both of which seem pretty
difficult to achieve non-recursively.<br class=3D"">
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>The proposal doesn=E2=80=99t eliminate any template recursion,=
it
eliminates [<font class=3D"" face=3D"Courier">make_</font>]<font
class=3D"" face=3D"Courier">index_sequence</font> uses and
attendant helper template declarations. </div>
</div>
</blockquote>
Using std::make_index_sequence just moves the recursion from the
call site into library code, which changes nothing from the
compiler's perspective (see below). That's what I meant when I
described it as "hiding some kinds of recursion in a library class."
<br>
<br>
In libstdc++v3 (gcc) the recursion lurks in this helper template:<br>
<br>
<tt>=C2=A0 template<size_t _Num></tt><tt><br>
</tt><tt>=C2=A0=C2=A0=C2=A0 struct _Build_index_tuple</tt><tt><br>
</tt><tt>=C2=A0=C2=A0=C2=A0 {</tt><tt><br>
</tt><tt>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 typedef typename _Build_index_t=
uple<_Num -
1>::__type::__next __type;</tt><tt><br>
</tt><tt>=C2=A0=C2=A0=C2=A0 };</tt><tt><br>
</tt><tt>=C2=A0 template<></tt><tt><br>
</tt><tt>=C2=A0=C2=A0=C2=A0 struct _Build_index_tuple<0></tt><tt>=
<br>
</tt><tt>=C2=A0=C2=A0=C2=A0 {</tt><tt><br>
</tt><tt>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 typedef _Index_tuple<> __=
type;</tt><tt><br>
</tt><tt>=C2=A0=C2=A0=C2=A0 };</tt><tt><br>
</tt><br>
In libc++ (clang), things are a *lot* more complex. It does 8x
unwinding of the recursion by means of helper template structs
__make, __repeat, __parity (an effort to improve compilation speed I
imagine). The actual recursion comes because the definitions of
__make and __parity mutually depend on each other. You can search
for "struct __parity" in the <a
href=3D"http://llvm.org/svn/llvm-project/libcxx/trunk/include/utility=
">source
browser</a> if you're interested in the gory details.<br>
<br>
If you want to get rid of the recursion entirely, you have to either
eliminate the need for std::make_index_sequence (e.g. by introducing
the sort of feature this proposal focuses on), or else implement it
non-recursively (again, using the sort of feature this proposal
focuses on). I'd strongly prefer the former because it eliminates
the boilerplate that users have to deal with when using
std::index_sequence.<br>
<br class=3D"">
<blockquote
cite=3D"mid:FBD72BF1-5E44-4B4E-90EA-3F726445819F@gmail.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<blockquote type=3D"cite" class=3D""><font class=3D""
face=3D"Courier">template < typename tuple_like ><b=
r
class=3D"">
int hash(tuple_like const &tup) {<br class=3D"">
=C2=A0 =C2=A0return hash( ... ^ std::get<=C2=A0</font>=
<span
style=3D"font-family: Courier;" class=3D"">unpack_sequenc=
e</span><font
class=3D"" face=3D"Courier">( std::tuple_size<
tuple_like >::value ) >( tup ) );<br class=3D"">
}</font></blockquote>
<br class=3D"">
In contrast, your unpack_sequence would have to "hoist" an
otherwise non-pack statement, giving it a second set of
variadic templates (the size_t... sequence). </div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div><font class=3D"" face=3D"Courier">unpack_sequence(N)</font>
would simply be an unexpanded pack (=C2=A714.5.3/6). =E2=80=9CHoi=
sting=E2=80=9D is
just what happens whenever you name a pack. The possibility of
an unexpanded pack in a non-template context is also part of
the price of N3728.</div>
</div>
</blockquote>
By "hoisting" I meant the use of an unexpanded parameter pack in a
context where one is not otherwise expected (thank you for helping
me nail that down with your concise statement). IMO that capability
is the main feature of N3728. Without the first-class parameter
packs that N3728 proposes, the notion of an unexpanded parameter
pack outside any variadic template context---or inside a variadic
template context, but in an expression that does not mention any of
the formal parameter packs---is completely foreign.<br>
<br>
BTW, even if something like N3728 were accepted, it does not provide
a clean mechanism for converting a parameter pack into a
<size_t...> pack, so this proposal would still be useful. It
does close an important gap, though, by providing a way to define
std::tuple non-recursively. <br>
<br class=3D"">
<blockquote
cite=3D"mid:FBD72BF1-5E44-4B4E-90EA-3F726445819F@gmail.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">N3728 woul=
d
give something nearly identical. Both create a new
parameter pack to be unpacked, in addition to any packs
that were already present.<br class=3D"">
<br class=3D"">
On the other hand, these "create-a-pack" approaches have
the benefit of *not* needing to explicitly bring in a
<typename...> pack. That could be useful at times,
such as the tuple_like idiom you make a good argument for
using. Creating a pack also means the code won't care
whether there are other packs around; nor would it care
whether those other packs are type, non-type, or template
template. <br class=3D"">
</div>
</div>
</blockquote>
<br class=3D"">
</div>
<div>Right.</div>
<div><br class=3D"">
</div>
<div>I see this as a dichotomy between two local optimums: If no
new keyword is allowed, the best solution is <font class=3D""
face=3D"Courier">indexed_type</font> because it doesn=E2=80=99t c=
are
whether the pack is type or non-type, it only requires a type in
a deduced pack pattern. </div>
</blockquote>
I'm not seeing how you could use indexed_type with non-type or
template template parameter packs. If you still want to pursue it in
spite of the flaws discussed earlier, could you provide an example?
<br>
<br>
<blockquote
cite=3D"mid:FBD72BF1-5E44-4B4E-90EA-3F726445819F@gmail.com"
type=3D"cite">
<div>If a new keyword is allowed, the best solution is <font
class=3D"" face=3D"Courier">unpack_sequence</font> because it
allows you to locally unpack things (even numeric sequences with
other pack basis), without introducing any new kind of entity to
the language.</div>
</blockquote>
Eh? It does require a new entity: an unexpanded parameter pack that
is not part of any enclosing variadic template definition. While it
might be tempting to hack it in quietly for this one (very limited)
use case, I suspect the Committee would much rather that any new
entity be fleshed out fully to avoid surprises and ugliness later
on, when people inevitably try to apply the concept in new and
unanticipated ways. <br>
<br>
That said, the unpack_sequence idea *is* tempting because it lets
you work with subsequences, an ability that __indexof() operator
would not provide. But I also feel like ability to slice and dice
parameter packs would be better integrated with N3728 or proposed as
a separate feature (which would fill the one remaining gap when
working with tuples, namely how to implement things like std::get
and std::tuple_element non-recursively). <br>
<br>
Ryan<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------060905070502070200090002--
.
Author: David Krauss <potswa@gmail.com>
Date: Sun, 26 Jul 2015 14:19:04 +0800
Raw View
--Apple-Mail=_1792F2E6-E0DF-4C21-B716-658F025CBFD4
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9307=E2=80=9325, at 11:18 PM, Ryan Johnson <scovich@gmail.c=
om> wrote:
>=20
> However... I just realized there's a glaring problem with this approach: =
it does not work with member functions of a template class. To give a simpl=
istic example:
>=20
> template <typename... Ts>
> struct my_tuple : std::tuple<Ts...>
> {
> using std::tuple<Ts...>::tuple;
> int hash()
> {
> /* Nothing to attach [[__index(Xs)]] to, nor std::indexed_type */
> }
> };
>=20
> There's no clear way to make my_tuple::hash() a template function in a wa=
y that allowed the necessary Ts,Xs pairing, because doing so would create a=
new/different typed parameter pack and hash() doesn't take any arguments t=
o kick-start deduction with. It also wouldn't work to require the Xs... at =
class level, because that would force the user to supply all the Xs when in=
stantiating the class. You couldn't hide the extra template parameters behi=
nd an alias template, because those suffer the same shortcoming.
Yeah, good point. It would be no improvement on the status quo here.
It=E2=80=99s a fatal flaw that it wouldn=E2=80=99t work with primary class =
templates, and that the obvious application of partial specialization would=
produce a template that isn=E2=80=99t actually more specialized than the p=
rimary.
> The __indexof operator doesn't suffer this problem because it can work di=
rectly with the existing parameter pack, rather than having to manufacture =
its own "special" one.
> =20
> Based on that, I'd say both the std::indexed_type<Ts,Xs> and Ts [[__index=
(Xs)]] ideas are out of the running.=20
=E2=80=A6
> I think I know enough that I could attempt a prototype of the Ts [[pack_i=
ndex(Xs)]] attribute approach to see whether it's easy or even possible to =
generate the extra parameter Xs parameter pack at the right moment.
>=20
> The std::indexed_type<Ts,Xs> flavor of magic would be a non-starter, thou=
gh, because there is no machinery in place to detect a "special" template c=
lass name (which could be obfuscated arbitrarily by use of typedefs and tem=
plate aliases).=20
Again, indexed_type is an alias template, so it vanishes before deduction b=
egins. indexed_type and [[pack_index(Xs)]] are one and the same solution. T=
here=E2=80=99s no class template involved.
>>> This proposal is just trying to eliminate a source of recursion and/or =
helper functions that these previous advances don't seem to have covered. T=
he main messiness that would be left is std::tuple and std::get, both of wh=
ich seem pretty difficult to achieve non-recursively.
>>=20
>> The proposal doesn=E2=80=99t eliminate any template recursion, it elimin=
ates [make_]index_sequence uses and attendant helper template declarations.
> Using std::make_index_sequence just moves the recursion from the call sit=
e into library code, which changes nothing from the compiler's perspective =
(see below). That's what I meant when I described it as "hiding some kinds =
of recursion in a library class."=20
It=E2=80=99s not really the same, since the library-internal helper gets me=
moized. All the optimizations you found in libc++, for instance, only matte=
r when first encountering a sequence that=E2=80=99s longer than anything ye=
t seen in the TU.
Also, std::tuple doesn=E2=80=99t actually get instantiated when it=E2=80=99=
s used only as a pack holder type. Pure metaprogramming shouldn=E2=80=99t e=
ver care whether it=E2=80=99s a complete class or not.
> By "hoisting" I meant the use of an unexpanded parameter pack in a contex=
t where one is not otherwise expected (thank you for helping me nail that d=
own with your concise statement). IMO that capability is the main feature o=
f N3728. Without the first-class parameter packs that N3728 proposes, the n=
otion of an unexpanded parameter pack outside any variadic template context=
---or inside a variadic template context, but in an expression that does no=
t mention any of the formal parameter packs---is completely foreign.
Disembodied template argument lists, and members that evaluate to pack expa=
nsions, are nothing to sneeze at, either.
> BTW, even if something like N3728 were accepted, it does not provide a cl=
ean mechanism for converting a parameter pack into a <size_t...> pack, so t=
his proposal would still be useful. It does close an important gap, though,=
by providing a way to define std::tuple non-recursively.=20
N3728 would allow something like
template< std::size_t len >
std::size_t ... unpack_sequence =3D std::make_index_sequence< len >::value =
....;
An operator to do the same would be redundant.
> I'm not seeing how you could use indexed_type with non-type or template t=
emplate parameter packs. If you still want to pursue it in spite of the fla=
ws discussed earlier, could you provide an example?=20
I don=E2=80=99t plan to pursue it, but the non-type pack would need to appe=
ar inside a template-id naming a type. For example:
template< int ... i, template< int > class ... tt, std::size_t ... x >
void f( std::indexed_type< tt< i >, x > ... );
>> If a new keyword is allowed, the best solution is unpack_sequence becaus=
e it allows you to locally unpack things (even numeric sequences with other=
pack basis), without introducing any new kind of entity to the language.
> Eh? It does require a new entity: an unexpanded parameter pack that is no=
t part of any enclosing variadic template definition.
Nothing in the language specification requires that unexpanded pack names m=
ust occur inside variadic template declarations. That just happens to be th=
e only way to get one.
It=E2=80=99s perhaps a new sort of entity to the implementation, but not to=
the language.
> While it might be tempting to hack it in quietly for this one (very limit=
ed) use case, I suspect the Committee would much rather that any new entity=
be fleshed out fully to avoid surprises and ugliness later on, when people=
inevitably try to apply the concept in new and unanticipated ways.=20
What potential complication? The grammar outside templates is the same as t=
he grammar inside. Non-dependent contexts are usually easier to process tha=
n dependent ones.
> That said, the unpack_sequence idea *is* tempting because it lets you wor=
k with subsequences, an ability that __indexof() operator would not provide=
.. But I also feel like ability to slice and dice parameter packs would be b=
etter integrated with N3728 or proposed as a separate feature (which would =
fill the one remaining gap when working with tuples, namely how to implemen=
t things like std::get and std::tuple_element non-recursively).=20
It seems like the proposals in this thread fall into a spectrum of degrees =
of decoupling between the numbers and the pack. indexof is most tightly cou=
pled because it goes into the pack expansion, indexed_type is less coupled =
because it goes into the pack declaration, and unpack_sequence is least cou=
pled because it goes anywhere and it only knows about an integral constant =
expression.
The way to implement std::tuple_element non-recursively is with an intrinsi=
c. Given non-recursive tuple_element, recursion disappears from std::get to=
o. This optimization apparently has a lower priority than the various other=
s that have already been implemented. If users are rolling their own tuple_=
element, that=E2=80=99s another problem that may be addressed by providing =
a more convenient interface, e.g.:
template< std::size_t n, typename ... t >
using nth_type =3D std::tuple_element_t< n, std::tuple< t ... > >;
FWIW, the only subsequences I=E2=80=99ve ever wanted are the nth element, t=
he tail sequence obtained by recursive list-unwinding, and the head sequenc=
e up to an element found by recursion (whose index is not known beforehand)=
.. These three cases each happen a lot, and they=E2=80=99re already the easy=
ones.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_1792F2E6-E0DF-4C21-B716-658F025CBFD4
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9307=
=E2=80=9325, at 11:18 PM, Ryan Johnson <<a href=3D"mailto:scovich@gmail.=
com" class=3D"">scovich@gmail.com</a>> wrote:</div><br class=3D"Apple-in=
terchange-newline"><div class=3D"">
=20
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
" class=3D"">
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<div class=3D"moz-cite-prefix">However... I just realized there's a gla=
ring problem with this
approach: it does not work with member functions of a template
class. To give a simplistic example:</div>
<br class=3D"">
template <typename... Ts><br class=3D"">
struct my_tuple : std::tuple<Ts...><br class=3D"">
{<br class=3D"">
using std::tuple<Ts...>::tuple;<br class=3D"">
int hash()<br class=3D"">
{<br class=3D"">
/* Nothing to attach [[__index(Xs)]] to,=
nor std::indexed_type
*/<br class=3D"">
}<br class=3D"">
};<br class=3D"">
<br class=3D"">
There's no clear way to make my_tuple::hash() a template function in
a way that allowed the necessary Ts,Xs pairing, because doing so
would create a new/different typed parameter pack and hash() doesn't
take any arguments to kick-start deduction with. It also wouldn't
work to require the Xs... at class level, because that would force
the user to supply all the Xs when instantiating the class. You
couldn't hide the extra template parameters behind an alias
template, because those suffer the same shortcoming.<br class=3D""></di=
v></div></blockquote><div><br class=3D""></div><div>Yeah, good point. It wo=
uld be no improvement on the status quo here.</div><div><br class=3D""></di=
v><div>It=E2=80=99s a fatal flaw that it wouldn=E2=80=99t work with primary=
class templates, and that the obvious application of partial specializatio=
n would produce a template that isn=E2=80=99t actually more specialized tha=
n the primary.<br class=3D""></div><br class=3D""><blockquote type=3D"cite"=
class=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=
=3D"">The __indexof operator doesn't suffer this problem because it can
work directly with the existing parameter pack, rather than having
to manufacture its own "special" one.<br class=3D"">
<br class=3D"">
Based on that, I'd say both the std::indexed_type<Ts,Xs> and
Ts [[__index(Xs)]] ideas are out of the running. <br class=3D"">
</div></div></blockquote>=E2=80=A6<br class=3D""><blockquote type=3D"ci=
te" class=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#000000" cl=
ass=3D"">I think I know enough that I could attempt a prototype of the Ts
[[pack_index(Xs)]] attribute approach to see whether it's easy or
even possible to generate the extra parameter Xs parameter pack at
the right moment.<br class=3D"">
<br class=3D"">
The std::indexed_type<Ts,Xs> flavor of magic would be a
non-starter, though, because there is no machinery in place to
detect a "special" template class name (which could be obfuscated
arbitrarily by use of typedefs and template aliases). <br class=3D""></=
div></div></blockquote><div><br class=3D""></div><div>Again, <font face=3D"=
Courier" class=3D"">indexed_type</font> is an alias template, so it vanishe=
s before deduction begins. <font face=3D"Courier" class=3D"">indexed_type</=
font> and <font face=3D"Courier" class=3D"">[[pack_index(Xs)]]</font> are o=
ne and the same solution. There=E2=80=99s no class template involved.</div>=
<div><br class=3D""></div><blockquote type=3D"cite" class=3D""><div class=
=3D""><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D""><blockquote cite=
=3D"mid:FBD72BF1-5E44-4B4E-90EA-3F726445819F@gmail.com" type=3D"cite" class=
=3D""><div class=3D""><blockquote type=3D"cite" class=3D""><div class=3D"">=
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">This
proposal is just trying to eliminate a source of recursion
and/or helper functions that these previous advances don't
seem to have covered. The main messiness that would be
left is std::tuple and std::get, both of which seem pretty
difficult to achieve non-recursively.<br class=3D"">
</div>
</div>
</blockquote>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">The proposal doesn=E2=80=99t eliminate any template=
recursion, it
eliminates [<font class=3D"" face=3D"Courier">make_</font>]<font =
class=3D"" face=3D"Courier">index_sequence</font> uses and
attendant helper template declarations. </div>
</div>
</blockquote>
Using std::make_index_sequence just moves the recursion from the
call site into library code, which changes nothing from the
compiler's perspective (see below). That's what I meant when I
described it as "hiding some kinds of recursion in a library class."
<br class=3D""></div></div></blockquote><div><br class=3D""></div><div>=
It=E2=80=99s not really the same, since the library-internal helper gets me=
moized. All the optimizations you found in libc++, for instance, only matte=
r when first encountering a sequence that=E2=80=99s longer than anything ye=
t seen in the TU.</div><div><br class=3D""></div><div>Also, <font face=
=3D"Courier" class=3D"">std::tuple</font> doesn=E2=80=99t actually get inst=
antiated when it=E2=80=99s used only as a pack holder type. Pure metaprogra=
mming shouldn=E2=80=99t ever care whether it=E2=80=99s a complete class or =
not.</div><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D=
""><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
By "hoisting" I meant the use of an unexpanded parameter pack in a
context where one is not otherwise expected (thank you for helping
me nail that down with your concise statement). IMO that capability
is the main feature of N3728. Without the first-class parameter
packs that N3728 proposes, the notion of an unexpanded parameter
pack outside any variadic template context---or inside a variadic
template context, but in an expression that does not mention any of
the formal parameter packs---is completely foreign.<br class=3D""></div=
></div></blockquote><div><br class=3D""></div><div>Disembodied template arg=
ument lists, and members that evaluate to pack expansions, are nothing to s=
neeze at, either.</div><br class=3D""><blockquote type=3D"cite" class=3D"">=
<div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">BTW, e=
ven if something like N3728 were accepted, it does not provide
a clean mechanism for converting a parameter pack into a
<size_t...> pack, so this proposal would still be useful. It
does close an important gap, though, by providing a way to define
std::tuple non-recursively. <br class=3D""></div></div></blockquote><di=
v><br class=3D""></div><div>N3728 would allow something like</div><div><br =
class=3D""></div><div><font face=3D"Courier" class=3D"">template< std::s=
ize_t len ></font></div><div><font face=3D"Courier" class=3D"">std::size=
_t ... unpack_sequence =3D std::make_index_sequence< len >::value ...=
;</font></div><div><br class=3D""></div><div>An operator to do the same wou=
ld be redundant.</div><br class=3D""><blockquote type=3D"cite" class=3D""><=
div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">I'm not=
seeing how you could use indexed_type with non-type or
template template parameter packs. If you still want to pursue it in
spite of the flaws discussed earlier, could you provide an example?
<br class=3D""></div></div></blockquote><div><br class=3D""></div><div>=
I don=E2=80=99t plan to pursue it, but the non-type pack would need to appe=
ar inside a template-id naming a type. For example:</div><div><br class=3D"=
"></div><div><font face=3D"Courier" class=3D"">template< int ... i, temp=
late< int > class ... tt, std::size_t ... x ></font></div><div><fo=
nt face=3D"Courier" class=3D"">void f( std::indexed_type< tt< i >,=
x > ... );</font></div><br class=3D""><blockquote type=3D"cite" class=
=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">=
<blockquote cite=3D"mid:FBD72BF1-5E44-4B4E-90EA-3F726445819F@gmail.com" typ=
e=3D"cite" class=3D""><div class=3D"">If a new keyword is allowed, the best=
solution is <font class=3D"" face=3D"Courier">unpack_sequence</font> becau=
se it
allows you to locally unpack things (even numeric sequences with
other pack basis), without introducing any new kind of entity to
the language.</div>
</blockquote>
Eh? It does require a new entity: an unexpanded parameter pack that
is not part of any enclosing variadic template definition. </div></div>=
</blockquote><div><br class=3D""></div><div>Nothing in the language specifi=
cation requires that unexpanded pack names must occur inside variadic templ=
ate declarations. That just happens to be the only way to get one.</div><di=
v><br class=3D""></div><div>It=E2=80=99s perhaps a new sort of entity to th=
e implementation, but not to the language.</div><br class=3D""><blockquote =
type=3D"cite" class=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#=
000000" class=3D"">While it
might be tempting to hack it in quietly for this one (very limited)
use case, I suspect the Committee would much rather that any new
entity be fleshed out fully to avoid surprises and ugliness later
on, when people inevitably try to apply the concept in new and
unanticipated ways. <br class=3D""></div></div></blockquote><div><br cl=
ass=3D""></div><div>What potential complication? The grammar outside templa=
tes is the same as the grammar inside. Non-dependent contexts are usually e=
asier to process than dependent ones.</div><br class=3D""><blockquote =
type=3D"cite" class=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#=
000000" class=3D"">That said, the unpack_sequence idea *is* tempting becaus=
e it lets
you work with subsequences, an ability that __indexof() operator
would not provide. But I also feel like ability to slice and dice
parameter packs would be better integrated with N3728 or proposed as
a separate feature (which would fill the one remaining gap when
working with tuples, namely how to implement things like std::get
and std::tuple_element non-recursively). <br class=3D""></div></div></b=
lockquote><br class=3D""></div><div>It seems like the proposals in this thr=
ead fall into a spectrum of degrees of decoupling between the numbers and t=
he pack. <font face=3D"Courier" class=3D"">indexof</font> is most tightly c=
oupled because it goes into the pack expansion, <font face=3D"Courier" clas=
s=3D"">indexed_type</font> is less coupled because it goes into the pack de=
claration, and <font face=3D"Courier" class=3D"">unpack_sequence</font> is =
least coupled because it goes anywhere and it only knows about an integral =
constant expression.</div><div><br class=3D""></div><div>The way to impleme=
nt <font face=3D"Courier" class=3D"">std::tuple_element</font> non-recursiv=
ely is with an intrinsic. Given non-recursive <span style=3D"font-fami=
ly: Courier;" class=3D"">tuple_element</span>, recursion disappears from <f=
ont face=3D"Courier" class=3D"">std::get</font> too. This optimization appa=
rently has a lower priority than the various others that have already been =
implemented. If users are rolling their own <font face=3D"Courier" class=3D=
"">tuple_element</font>, that=E2=80=99s another problem that may be address=
ed by providing a more convenient interface, e.g.:</div><div><br class=3D""=
></div><div><font face=3D"Courier" class=3D"">template< std::size_t n, t=
ypename ... t ></font></div><div><font face=3D"Courier" class=3D"">using=
nth_type =3D std::tuple_element_t< n, std::tuple< t ... > >;</=
font></div><br class=3D""><div class=3D"">FWIW, the only subsequences I=E2=
=80=99ve ever wanted are the nth element, the tail sequence obtained by rec=
ursive list-unwinding, and the head sequence up to an element found by recu=
rsion (whose index is not known beforehand). These three cases each happen =
a lot, and they=E2=80=99re already the easy ones.</div><div class=3D""><br =
class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_1792F2E6-E0DF-4C21-B716-658F025CBFD4--
.
Author: Edward Catmur <ed@catmur.co.uk>
Date: Sun, 26 Jul 2015 15:52:47 -0700 (PDT)
Raw View
------=_Part_2522_1560834070.1437951167968
Content-Type: text/plain; charset=UTF-8
std::get is already nonrecursive in any modern implementation using variadic inheritance. Admittedly, you still need recursion to generate the index_sequence - but as you pointed out above, that gets memoized for any N and smaller.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2522_1560834070.1437951167968--
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 27 Jul 2015 09:59:58 +0800
Raw View
--Apple-Mail=_2D07836F-7A6E-40B7-8C57-295D7CD4C87F
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9307=E2=80=9327, at 6:52 AM, Edward Catmur <ed@catmur.co.uk=
> wrote:
>=20
> std::get is already nonrecursive in any modern implementation using varia=
dic inheritance. Admittedly, you still need recursion to generate the index=
_sequence - but as you pointed out above, that gets memoized for any N and =
smaller.=20
The return type of std::get is usually determined by std::tuple_element, so=
my assertion is that a nonrecursive tuple_element implies a nonrecursive g=
et.
It=E2=80=99s also possible to eliminate the tuple_element metafunction by r=
eplacing it with C++14 deduced return type. That would require the tuple ba=
se classes (one per element) to have types like __tuple_base< tuple< elemen=
t ... >, index > whereas current implementations use something like __tuple=
_base< element, index >.
If it=E2=80=99s really such a win to eliminate template recursion from std:=
:get, implementations already have various means to do so.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_2D07836F-7A6E-40B7-8C57-295D7CD4C87F
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9307=
=E2=80=9327, at 6:52 AM, Edward Catmur <<a href=3D"mailto:ed@catmur.co.u=
k" class=3D"">ed@catmur.co.uk</a>> wrote:</div><br class=3D"Apple-interc=
hange-newline"><div class=3D""><span style=3D"font-family: Helvetica; font-=
size: 12px; font-style: normal; font-variant: normal; font-weight: normal; =
letter-spacing: normal; line-height: normal; orphans: auto; text-align: sta=
rt; text-indent: 0px; text-transform: none; white-space: normal; widows: au=
to; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display=
: inline !important;" class=3D"">std::get is already nonrecursive in any mo=
dern implementation using variadic inheritance. Admittedly, you still need =
recursion to generate the index_sequence - but as you pointed out above, th=
at gets memoized for any N and smaller.<span class=3D"Apple-converted-space=
"> </span></span><br style=3D"font-family: Helvetica; font-size: 12px;=
font-style: normal; font-variant: normal; font-weight: normal; letter-spac=
ing: normal; line-height: normal; orphans: auto; text-align: start; text-in=
dent: 0px; text-transform: none; white-space: normal; widows: auto; word-sp=
acing: 0px; -webkit-text-stroke-width: 0px;" class=3D""></div></blockquote>=
</div><br class=3D""><div class=3D"">The return type of <font face=3D"Couri=
er" class=3D"">std::get</font> is usually determined by <font face=3D"Couri=
er" class=3D"">std::tuple_element</font>, so my assertion is that a nonrecu=
rsive <font face=3D"Courier" class=3D"">tuple_element</font> implies a nonr=
ecursive <font face=3D"Courier" class=3D"">get</font>.</div><div class=3D""=
><br class=3D""></div><div class=3D"">It=E2=80=99s also possible to elimina=
te the <font face=3D"Courier" class=3D"">tuple_element</font> metafunction =
by replacing it with C++14 deduced return type. That would require the tupl=
e base classes (one per element) to have types like <font face=3D"Courier" =
class=3D"">__tuple_base< tuple< element ... >, index ></font> w=
hereas current implementations use something like <font face=3D"Courier" cl=
ass=3D"">__tuple_base< </font><span style=3D"font-family: Courier;"=
class=3D"">element</span><font face=3D"Courier" class=3D"">, index ></f=
ont>.</div><div class=3D""><br class=3D""></div><div class=3D"">If it=E2=80=
=99s really such a win to eliminate template recursion from <font face=3D"C=
ourier" class=3D"">std::get</font>, implementations already have various me=
ans to do so.</div><div class=3D""><br class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_2D07836F-7A6E-40B7-8C57-295D7CD4C87F--
.
Author: Edward Catmur <ed@catmur.co.uk>
Date: Mon, 27 Jul 2015 01:23:08 -0700 (PDT)
Raw View
------=_Part_96_1275771877.1437985388474
Content-Type: multipart/alternative;
boundary="----=_Part_97_1128940550.1437985388481"
------=_Part_97_1128940550.1437985388481
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, 27 July 2015 03:00:04 UTC+1, David Krauss wrote:
>
> The return type of std::get is usually determined by std::tuple_element,=
=20
> so my assertion is that a nonrecursive tuple_element implies a=20
> nonrecursive get.
>
> It=E2=80=99s also possible to eliminate the tuple_element metafunction by=
=20
> replacing it with C++14 deduced return type. That would require the tuple=
=20
> base classes (one per element) to have types like __tuple_base< tuple<=20
> element ... >, index > whereas current implementations use something like=
=20
> __tuple_base< element, index >.
>
Actually, you can have nonrecursive get without having to put all the=20
elements into tuple_base. I find the most natural implementation is the=20
following:
template<std::size_t I, class T> T& tuple_get(tuple_base<I, T>& obj) {=20
return obj.value; }
If you call tuple_get<N> on the variadically derived class then everything=
=20
gets sorted out by overload resolution on the implicit object parameter.
Similarly, there's a nice trick using variadic inheritance to compute=20
tuple_element (and/or nth_type) without recursion or any magic:
template<bool, class> struct nth_type_base {};
template<class T> struct nth_type_base<true, T> { using type =3D T; };
template<std::size_t I, class...> struct nth_type_impl;
template<std::size_t I, std::size_t... Is, class... Ts>
struct nth_type_impl<I, std::index_sequence<Is...>, Ts...> : nth_type_bas=
e
<I =3D=3D Is, Ts>... {};
template<std::size_t I, class T> struct tuple_element;
template<std::size_t I, class... Ts>
struct tuple_element<I, tuple<Ts...>> : nth_type_impl<I, std::
index_sequence_for<Ts...>, Ts...> {};
If it=E2=80=99s really such a win to eliminate template recursion from std:=
:get,=20
> implementations already have various means to do so.
>
=20
Definitely - and as you say, it's surprising that they haven't yet.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_97_1128940550.1437985388481
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, 27 July 2015 03:00:04 UTC+1, David Krauss wrote:<blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left-width: 1p=
x; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding=
-left: 1ex;"><div style=3D"word-wrap: break-word;"><div>The return type of=
=C2=A0<font face=3D"Courier">std::get</font>=C2=A0is usually determined by=
=C2=A0<font face=3D"Courier">std::tuple_element</font>, so my assertion is =
that a nonrecursive=C2=A0<font face=3D"Courier">tuple_element</font>=C2=A0i=
mplies a nonrecursive=C2=A0<font face=3D"Courier">get</font>.</div><div><br=
></div><div>It=E2=80=99s also possible to eliminate the=C2=A0<font face=3D"=
Courier">tuple_element</font>=C2=A0metafunction by replacing it with C++14 =
deduced return type. That would require the tuple base classes (one per ele=
ment) to have types like=C2=A0<font face=3D"Courier">__tuple_base< tuple=
< element ... >, index ></font>=C2=A0whereas current implementatio=
ns use something like=C2=A0<font face=3D"Courier">__tuple_base<=C2=A0</f=
ont><span style=3D"font-family: Courier;">element</span><font face=3D"Couri=
er">, index ></font>.</div></div></blockquote><div><br></div><div>Actual=
ly, you can have nonrecursive get without having to put all the elements in=
to tuple_base. I find the most natural implementation is the following:</di=
v><div><br></div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(=
187, 187, 187); word-wrap: break-word; background-color: rgb(250, 250, 250)=
;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D=
"color: #008;" class=3D"styled-by-prettify">template</span><span style=3D"c=
olor: #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=
"styled-by-prettify">size_t I</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>class</span><span style=3D"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"> T</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> tuple_get</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify">tuple_base</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">I</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-prettif=
y">>&</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> obj</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"> </span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">return</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> obj</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"styl=
ed-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: #660;" class=3D"styled-by-prettify">}</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div=
></code></div><div><br>If you call tuple_get<N> on the variadically d=
erived class then everything gets sorted out by overload resolution on the =
implicit object parameter.</div><div><br></div><div>Similarly, there's =
a nice trick using variadic inheritance to compute tuple_element (and/or nt=
h_type) without recursion or any magic:</div><div><br></div><div class=3D"p=
rettyprint" style=3D"border: 1px solid rgb(187, 187, 187); word-wrap: break=
-word; background-color: rgb(250, 250, 250);"><code class=3D"prettyprint"><=
div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">template</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify"><</span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">bool</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">class</span><span st=
yle=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">struct</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"> nth_type_base </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: #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"> =
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">struct</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> nth_type_base=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">true</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-b=
y-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettif=
y">using</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> t=
ype </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</s=
pan><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: #000;"=
class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">template</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify"><</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">size_t I</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">class</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">...></span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">struct</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> nth_type_impl</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">template</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify"><</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">size_t I</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 sty=
le=3D"color: #660;" class=3D"styled-by-prettify">...</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #60=
6;" class=3D"styled-by-prettify">Is</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: #008;" class=3D"styled-by-pre=
ttify">class</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">...</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #606;" class=3D"styled-by-prettify">Ts</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">></span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">struct</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> nth_type_impl</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">I</span><span style=3D"color: #66=
0;" 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"st=
yled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">index_sequence</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify"><</span><span style=3D"color: #606;" class=3D"styled-by-pr=
ettify">Is</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;" class=3D"styled-by-prettify">Ts</span><s=
pan 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"> nth_type_base</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">I </span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">=3D=3D</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #606;" class=3D"styled-b=
y-prettify">Is</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </sp=
an><span style=3D"color: #606;" class=3D"styled-by-prettify">Ts</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">>...</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"co=
lor: #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: #008=
;" class=3D"styled-by-prettify">template</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">size_t I</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">class</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span s=
tyle=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">struct</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"> tuple_element</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: #660;" class=
=3D"styled-by-prettify"><</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">size_t I</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">class</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;" class=3D"styled-by-prettify">Ts</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">></span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">struct</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> tuple_element</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify"><</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">I</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> tuple</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><=
;</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Ts</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">...>></span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">:</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> nth_type_impl</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">I</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"st=
yled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">index_sequence_for</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify"><</span><span style=3D"color: #606;" class=3D"styled-b=
y-prettify">Ts</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">...>,</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #606;" class=3D"styled-by-prettify">Ts</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">...></span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">{};</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br></span></div></code></div><div=
><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left=
: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-=
wrap:break-word"><div>If it=E2=80=99s really such a win to eliminate templa=
te recursion from <font face=3D"Courier">std::get</font>, implementations a=
lready have various means to do so.</div></div></blockquote><div>=C2=A0</di=
v><div>Definitely - and as you say, it's surprising that they haven'=
;t yet.</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_97_1128940550.1437985388481--
------=_Part_96_1275771877.1437985388474--
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 27 Jul 2015 19:13:22 +0800
Raw View
--Apple-Mail=_29CE40E0-A539-47CA-BBB5-29228F6F4F31
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9307=E2=80=9327, at 4:23 PM, Edward Catmur <ed@catmur.co.uk=
> wrote:
>=20
> Actually, you can have nonrecursive get without having to put all the ele=
ments into tuple_base. I find the most natural implementation is the follow=
ing:
>=20
> template<std::size_t I, class T> T& tuple_get(tuple_base<I, T>& obj) { re=
turn obj.value; }
>=20
> If you call tuple_get<N> on the variadically derived class then everythin=
g gets sorted out by overload resolution on the implicit object parameter.
We=E2=80=99re getting a bit off topic here, but you can=E2=80=99t get class=
T without using recursion in the form of tuple_element.
You can implement get without changing __tuple_base, by using overload reso=
lution over indexed dispatch tags, but that adds inefficiency.
Naming the derived type tuple<T...> as a template argument merely mentions =
a preexisting specialization, which doesn=E2=80=99t require any extra compi=
ler resources. Anyway, the same effect could be achieved by nesting tuple_b=
ase inside a class parameterized on <T...>.
Here=E2=80=99s a working proof of concept. amalgam_ftor can be found here <=
https://code.google.com/p/c-plus/source/browse/src/util.h>.
template< typename t >
struct tag {
typedef t type;
};
template< typename ... elem >
struct tuple_impl {
template< typename e, std::size_t x >
struct type_map_entry {
tag< e > operator () ( std::integral_constant< std::size_t, x > );
};
template< typename =3D std::make_index_sequence< sizeof ... (elem) > >
struct type_map;
template< std::size_t ... x >
struct type_map< std::index_sequence< x ... > > {
typedef amalgam_ftor< type_map_entry< elem, x > ... > type;
};
template< std::size_t x >
struct tuple_entry {
typename decltype( typename type_map<>::type{}( std::integral_const=
ant< std::size_t, x >{} ) )::type value;
template< typename ... arg >
tuple_entry( arg && ... a )
: value( std::forward< arg >( a ) ... ) {}
};
template< typename =3D std::make_index_sequence< sizeof ... (elem) > >
struct base;
template< std::size_t ... x >
struct base< std::index_sequence< x ... > >
: tuple_entry< x > ... {
// Most of the std::tuple implementation goes here.
};
};
template< typename ... elem >
struct tuple
: tuple_impl< elem ... >::template base<> {
using tuple_impl< elem ... >::template base<>::base;
};
// test
extern tuple< int, char, long > q;
char c =3D { q.tuple_entry< 1 >::value }; // no narrowing =3D> it found the=
type
The complexity here is in forming and using the overload set at the time tu=
ple is instantiated. Hopefully all the bootstrap stuff (overload set, etc) =
gets garbage collected, and what=E2=80=99s left is an ideal map from number=
s, through base classes, to types.
> Similarly, there's a nice trick using variadic inheritance to compute tup=
le_element (and/or nth_type) without recursion or any magic:
I remembered that something like that existed, but couldn=E2=80=99t remembe=
r how, and didn=E2=80=99t find it in the current libc++. I think that recur=
sion is more efficient in practice.
That particular form of the trick requires N instantiations, so it looks le=
ss efficient than recursion. Unless you have a parallelized template engine=
, recursion will win by early exit.
> If it=E2=80=99s really such a win to eliminate template recursion from st=
d::get, implementations already have various means to do so.
> =20
> Definitely - and as you say, it's surprising that they haven't yet.
I didn=E2=80=99t say it was surprising. In my experience, when a metaprogra=
m needs random access, an overload set is a better tool. Instantiating very=
large std::tuple objects is a red flag. std::tuple_element really shouldn=
=E2=80=99t be a bottleneck. Implementation effort is better spent optimizin=
g the real fundamentals: name lookup, class template instantiation, overloa=
d resolution constexpr evaluation, etc. The true performance culprits can b=
e found by running real workloads in profiler, and there=E2=80=99s no sense=
in second guessing the work of guys who do that.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_29CE40E0-A539-47CA-BBB5-29228F6F4F31
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9307=
=E2=80=9327, at 4:23 PM, Edward Catmur <<a href=3D"mailto:ed@catmur.co.u=
k" class=3D"">ed@catmur.co.uk</a>> wrote:</div><br class=3D"Apple-interc=
hange-newline"><div class=3D""><div class=3D"">Actually, you can have nonre=
cursive get without having to put all the elements into tuple_base. I find =
the most natural implementation is the following:</div><div class=3D""><br =
class=3D""></div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(=
187, 187, 187); word-wrap: break-word; background-color: rgb(250, 250, 250)=
;"><code class=3D"prettyprint"><span style=3D"color: #008;" class=3D"styled=
-by-prettify">template</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify"><</span>std<span style=3D"color: #660;" class=3D"styled-by-p=
rettify">::</span>size_t I<span style=3D"color: #660;" class=3D"styled-by-p=
rettify">,</span> <span style=3D"color: #008;" class=3D"styled-by-prettify"=
>class</span> T<span style=3D"color: #660;" class=3D"styled-by-prettify">&g=
t;</span> T<span style=3D"color: #660;" class=3D"styled-by-prettify">&<=
/span> tuple_get<span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span>tuple_base<span style=3D"color: #660;" class=3D"styled-by-prettify">=
<</span>I<span style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an> T<span style=3D"color: #660;" class=3D"styled-by-prettify">>&</s=
pan> obj<span style=3D"color: #660;" class=3D"styled-by-prettify">)</span> =
<span style=3D"color: #660;" class=3D"styled-by-prettify">{</span> <span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">return</span> obj<span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">.</span>value<span style=
=3D"color: #660;" class=3D"styled-by-prettify">;</span> <span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">}</span><br class=3D""></code></div>=
<div class=3D""><br class=3D"">If you call tuple_get<N> on the variad=
ically derived class then everything gets sorted out by overload resolution=
on the implicit object parameter.</div><div class=3D""></div></div></block=
quote><div><br class=3D""></div><div>We=E2=80=99re getting a bit off topic =
here, but you can=E2=80=99t get <font face=3D"Courier" class=3D"">class T</=
font> without using recursion in the form of <font face=3D"Courier" class=
=3D"">tuple_element</font>.</div><div><br class=3D""></div><div>You can imp=
lement <font face=3D"Courier" class=3D"">get</font> without changing <font =
face=3D"Courier" class=3D"">__tuple_base</font>, by using overload resoluti=
on over indexed dispatch tags, but that adds inefficiency.</div><div><br cl=
ass=3D""></div><div>Naming the derived type <font face=3D"Courier" class=3D=
"">tuple<T...></font> as a template argument merely mentions a p=
reexisting specialization, which doesn=E2=80=99t require any extra compiler=
resources. Anyway, the same effect could be achieved by nesting <font face=
=3D"Courier" class=3D"">tuple_base</font> inside a class parameterized on <=
font face=3D"Courier" class=3D""><T...></font>.</div><div><br class=
=3D""></div><div>Here=E2=80=99s a working proof of concept. <font face=
=3D"Courier" class=3D"">amalgam_ftor</font> can be found <a href=3D"ht=
tps://code.google.com/p/c-plus/source/browse/src/util.h" class=3D"">here</a=
>.</div><div><br class=3D""></div><div><font face=3D"Courier" class=3D"">te=
mplate< typename t ><br class=3D"">struct tag {<br class=3D""> =
typedef t type;<br class=3D"">};<br class=3D""><br class=3D"">t=
emplate< typename ... elem ><br class=3D"">struct tuple_impl {<br cla=
ss=3D""> template< typename e, std::size_t x ><br c=
lass=3D""> struct type_map_entry {<br class=3D""> &=
nbsp; tag< e > operator () ( std::integral_constan=
t< std::size_t, x > );<br class=3D""> };<br class=
=3D""><br class=3D""> template< typename =3D std::make=
_index_sequence< sizeof ... (elem) > ><br class=3D""> =
struct type_map;<br class=3D""><br class=3D""> temp=
late< std::size_t ... x ><br class=3D""> struct typ=
e_map< std::index_sequence< x ... > > {<br class=3D""> &n=
bsp; typedef amalgam_ftor< type_map_entry< elem, x=
> ... > type;<br class=3D""> };<br class=3D""><br =
class=3D""> template< std::size_t x ><br class=3D""=
> struct tuple_entry {<br class=3D""> =
typename decltype( typename type_map<>::type{}( std::int=
egral_constant< std::size_t, x >{} ) )::type value;<br class=3D""><br=
class=3D""> template< typename ... arg =
><br class=3D""> tuple_entry( arg &&=
amp; ... a )<br class=3D""> :=
value( std::forward< arg >( a ) ... ) {}<br class=3D""> =
};<br class=3D""><br class=3D""> template< typen=
ame =3D std::make_index_sequence< sizeof ... (elem) > ><br class=
=3D""> struct base;<br class=3D""><br class=3D""> &=
nbsp; template< std::size_t ... x ><br class=3D""> &=
nbsp;struct base< std::index_sequence< x ... > ><br class=3D"">=
: tuple_entry< x > ... {<br class=3D=
""> // Most of the std::tuple implementatio=
n goes here.<br class=3D""> };<br class=3D"">};<br class=
=3D""><br class=3D"">template< typename ... elem ><br class=3D"">stru=
ct tuple<br class=3D""> : tuple_impl< elem ... >::t=
emplate base<> {<br class=3D""> using tuple_impl<=
; elem ... >::template base<>::base;<br class=3D"">};</font></div>=
<div><font face=3D"Courier" class=3D""><br class=3D""></font></div><div><fo=
nt face=3D"Courier" class=3D"">// test<br class=3D"">extern tuple< int, =
char, long > q;<br class=3D"">char c =3D { q.tuple_entry< 1 >::val=
ue }; // no narrowing =3D> it found the type<br class=3D""></font><=
br class=3D""></div><div>The complexity here is in forming and using the ov=
erload set at the time <font face=3D"Courier" class=3D"">tuple</font> is in=
stantiated. Hopefully all the bootstrap stuff (overload set, etc) gets garb=
age collected, and what=E2=80=99s left is an ideal map from numbers, throug=
h base classes, to types.</div><div><br class=3D""></div><blockquote type=
=3D"cite" class=3D""><div class=3D""><div class=3D"">Similarly, there's a n=
ice trick using variadic inheritance to compute tuple_element (and/or nth_t=
ype) without recursion or any magic:</div></div></blockquote><div><br class=
=3D""></div><div>I remembered that something like that existed, but couldn=
=E2=80=99t remember how, and didn=E2=80=99t find it in the current libc++. =
I think that recursion is more efficient in practice.</div><div><br class=
=3D""></div><div>That particular form of the trick requires N instantiation=
s, so it looks less efficient than recursion. Unless you have a parallelize=
d template engine, recursion will win by early exit.</div><br class=3D""><b=
lockquote type=3D"cite" class=3D""><div class=3D""><blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div style=3D"word-wrap:break-word" class=3D""><div cl=
ass=3D"">If it=E2=80=99s really such a win to eliminate template recursion =
from <font face=3D"Courier" class=3D"">std::get</font>, implementations alr=
eady have various means to do so.</div></div></blockquote><div class=3D"">&=
nbsp;</div><div class=3D"">Definitely - and as you say, it's surprising tha=
t they haven't yet.</div></div></blockquote><br class=3D""></div><div>I did=
n=E2=80=99t say it was surprising. In my experience, when a metaprogram nee=
ds random access, an overload set is a better tool. Instantiating very larg=
e <font face=3D"Courier" class=3D"">std::tuple</font> objects is a red=
flag. <font face=3D"Courier" class=3D"">std::tuple_element</font> really s=
houldn=E2=80=99t be a bottleneck. Implementation effort is better spent opt=
imizing the real fundamentals: name lookup, class template instantiation, o=
verload resolution constexpr evaluation, etc. The true performance culprits=
can be found by running real workloads in profiler, and there=E2=80=99s no=
sense in second guessing the work of guys who do that.</div><br class=3D""=
></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_29CE40E0-A539-47CA-BBB5-29228F6F4F31--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Mon, 27 Jul 2015 06:40:06 -0600
Raw View
This is a multi-part message in MIME format.
--------------040500010700030203030407
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 27/07/2015 5:13 AM, David Krauss wrote:
>
>> On 2015=E2=80=9307=E2=80=9327, at 4:23 PM, Edward Catmur <ed@catmur.co.u=
k=20
>> <mailto:ed@catmur.co.uk>> wrote:
>>
>> Actually, you can have nonrecursive get without having to put all the=20
>> elements into tuple_base. I find the most natural implementation is=20
>> the following:
>>
>> |template<std::size_t I, class T> T& tuple_get(tuple_base<I, T>& obj)=20
>> { return obj.value; }
>> |
>>
>> If you call tuple_get<N> on the variadically derived class then=20
>> everything gets sorted out by overload resolution on the implicit=20
>> object parameter.
>
> We=E2=80=99re getting a bit off topic here, but you can=E2=80=99t get cla=
ss T without=20
> using recursion in the form of tuple_element.
>
> You can implement get without changing __tuple_base, by using overload=20
> resolution over indexed dispatch tags, but that adds inefficiency.
>
> Naming the derived type tuple<T...> as a template argument merely=20
> mentions a preexisting specialization, which doesn=E2=80=99t require any =
extra=20
> compiler resources. Anyway, the same effect could be achieved by=20
> nesting tuple_base inside a class parameterized on <T...>.
>
> Here=E2=80=99s a working proof of concept. amalgam_ftor can be found here=
=20
> <https://code.google.com/p/c-plus/source/browse/src/util.h>.
>
> template< typename t >
> struct tag {
> typedef t type;
> };
>
> template< typename ... elem >
> struct tuple_impl {
> template< typename e, std::size_t x >
> struct type_map_entry {
> tag< e > operator () ( std::integral_constant< std::size_t, x > )=
;
> };
>
> template< typename =3D std::make_index_sequence< sizeof ... (elem) > =
>
> struct type_map;
>
> template< std::size_t ... x >
> struct type_map< std::index_sequence< x ... > > {
> typedef amalgam_ftor< type_map_entry< elem, x > ... > type;
> };
>
> template< std::size_t x >
> struct tuple_entry {
> typename decltype( typename type_map<>::type{}(=20
> std::integral_constant< std::size_t, x >{} ) )::type value;
>
> template< typename ... arg >
> tuple_entry( arg && ... a )
> : value( std::forward< arg >( a ) ... ) {}
> };
>
> template< typename =3D std::make_index_sequence< sizeof ... (elem) > =
>
> struct base;
>
> template< std::size_t ... x >
> struct base< std::index_sequence< x ... > >
> : tuple_entry< x > ... {
> // Most of the std::tuple implementation goes here.
> };
> };
>
> template< typename ... elem >
> struct tuple
> : tuple_impl< elem ... >::template base<> {
> using tuple_impl< elem ... >::template base<>::base;
> };
>
> // test
> extern tuple< int, char, long > q;
> char c =3D { q.tuple_entry< 1 >::value }; // no narrowing =3D> it found=
=20
> the type
>
> The complexity here is in forming and using the overload set at the=20
> time tuple is instantiated. Hopefully all the bootstrap stuff=20
> (overload set, etc) gets garbage collected, and what=E2=80=99s left is an=
=20
> ideal map from numbers, through base classes, to types.
That's very clever. The recursion is still there---hiding in=20
amalgam_ftor's abuse of std::common_type ---but at least it only has to=20
happen once when a instantiating each kind of tuple that way.
FYI, the code fails to compile with gcc-4.9.
First problem is minor: struct amalgam has no default constructor=20
(needed when playing with the type_map decltype stuff). Solution is to=20
either add "amalgam() =3D default" to the amalgam class definition, or to=
=20
use std::declval<> inside the decltype() to obtain an amalgam instance.
Second problem is weird: "error: request for member =E2=80=98tuple_entry=E2=
=80=99 is=20
ambiguous" (naming tuple_entry<2>, tuple_entry<1>, and tuple_entry<0> as=20
candidates). Compiles fine with clang-3.6, so I don't know whether it's=20
a gcc bug or if your code relies on a clang-ism. I suspect the former=20
since I see no reason why asking for tuple_entry<1> should consider=20
tuple_entry<0> or tuple_entry<2> at all, let alone consider them to be=20
ambiguous.
Ryan
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------040500010700030203030407
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 27/07/2015 5:13 AM, David Krauss
wrote:<br>
</div>
<blockquote
cite=3D"mid:2A5DC0EE-7E82-44AC-89E9-AE625BBFBAC7@gmail.com"
type=3D"cite">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8">
<br class=3D"">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">On 2015=E2=80=9307=E2=80=9327, at 4:23 PM, Edward=
Catmur <<a
moz-do-not-send=3D"true" href=3D"mailto:ed@catmur.co.uk"
class=3D"">ed@catmur.co.uk</a>> wrote:</div>
<br class=3D"Apple-interchange-newline">
<div class=3D"">
<div class=3D"">Actually, you can have nonrecursive get
without having to put all the elements into tuple_base. I
find the most natural implementation is the following:</div>
<div class=3D""><br class=3D"">
</div>
<div class=3D"prettyprint" style=3D"border: 1px solid rgb(187,
187, 187); word-wrap: break-word; background-color:
rgb(250, 250, 250);"><code class=3D"prettyprint"><span
style=3D"color: #008;" class=3D"styled-by-prettify">templ=
ate</span><span
style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span>std<span
style=3D"color: #660;" class=3D"styled-by-prettify">::</s=
pan>size_t
I<span style=3D"color: #660;" class=3D"styled-by-prettify">=
,</span>
<span style=3D"color: #008;" class=3D"styled-by-prettify">c=
lass</span>
T<span style=3D"color: #660;" class=3D"styled-by-prettify">=
></span>
T<span style=3D"color: #660;" class=3D"styled-by-prettify">=
&</span>
tuple_get<span style=3D"color: #660;"
class=3D"styled-by-prettify">(</span>tuple_base<span
style=3D"color: #660;" class=3D"styled-by-prettify"><<=
/span>I<span
style=3D"color: #660;" class=3D"styled-by-prettify">,</sp=
an>
T<span style=3D"color: #660;" class=3D"styled-by-prettify">=
>&</span>
obj<span style=3D"color: #660;" 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">r=
eturn</span>
obj<span style=3D"color: #660;" class=3D"styled-by-prettify=
">.</span>value<span
style=3D"color: #660;" class=3D"styled-by-prettify">;</sp=
an>
<span style=3D"color: #660;" class=3D"styled-by-prettify">}=
</span><br
class=3D"">
</code></div>
<div class=3D""><br class=3D"">
If you call tuple_get<N> on the variadically derived
class then everything gets sorted out by overload
resolution on the implicit object parameter.</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>We=E2=80=99re getting a bit off topic here, but you can=E2=80=
=99t get <font
class=3D"" face=3D"Courier">class T</font> without using
recursion in the form of <font class=3D"" face=3D"Courier">tuple_=
element</font>.</div>
<div><br class=3D"">
</div>
<div>You can implement <font class=3D"" face=3D"Courier">get</font>
without changing <font class=3D"" face=3D"Courier">__tuple_base</=
font>,
by using overload resolution over indexed dispatch tags, but
that adds inefficiency.</div>
<div><br class=3D"">
</div>
<div>Naming the derived type <font class=3D"" face=3D"Courier">tupl=
e<T...></font>
as a template argument=C2=A0merely mentions a preexisting
specialization, which doesn=E2=80=99t require any extra compiler
resources. Anyway, the same effect could be achieved by
nesting <font class=3D"" face=3D"Courier">tuple_base</font>
inside a class parameterized on <font class=3D"" face=3D"Courier"=
><T...></font>.</div>
<div><br class=3D"">
</div>
<div>Here=E2=80=99s a working proof of concept.=C2=A0<font class=3D=
""
face=3D"Courier">amalgam_ftor</font> can be found=C2=A0<a
moz-do-not-send=3D"true"
href=3D"https://code.google.com/p/c-plus/source/browse/src/util=
..h"
class=3D"">here</a>.</div>
<div><br class=3D"">
</div>
<div><font class=3D"" face=3D"Courier">template< typename t >=
<br
class=3D"">
struct tag {<br class=3D"">
=C2=A0 =C2=A0=C2=A0typedef t type;<br class=3D"">
};<br class=3D"">
<br class=3D"">
template< typename ... elem ><br class=3D"">
struct tuple_impl {<br class=3D"">
=C2=A0 =C2=A0=C2=A0template< typename e, std::size_t x ><=
br class=3D"">
=C2=A0 =C2=A0=C2=A0struct type_map_entry {<br class=3D"">
=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0tag< e > operator () (
std::integral_constant< std::size_t, x > );<br
class=3D"">
=C2=A0 =C2=A0=C2=A0};<br class=3D"">
<br class=3D"">
=C2=A0 =C2=A0=C2=A0template< typename =3D std::make_index_se=
quence<
sizeof ... (elem) > ><br class=3D"">
=C2=A0 =C2=A0=C2=A0struct type_map;<br class=3D"">
<br class=3D"">
=C2=A0 =C2=A0=C2=A0template< std::size_t ... x ><br class=
=3D"">
=C2=A0 =C2=A0=C2=A0struct type_map< std::index_sequence< =
x ... >
> {<br class=3D"">
=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0typedef amalgam_ftor< type_=
map_entry< elem, x
> ... > type;<br class=3D"">
=C2=A0 =C2=A0=C2=A0};<br class=3D"">
<br class=3D"">
=C2=A0 =C2=A0=C2=A0template< std::size_t x ><br class=3D"=
">
=C2=A0 =C2=A0=C2=A0struct tuple_entry {<br class=3D"">
=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0typename decltype( typename
type_map<>::type{}( std::integral_constant<
std::size_t, x >{} ) )::type value;<br class=3D"">
<br class=3D"">
=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0template< typename ... arg =
><br class=3D"">
=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0tuple_entry( arg && ..=
.. a )<br class=3D"">
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0: value( std::fo=
rward< arg >( a ) ... ) {}<br
class=3D"">
=C2=A0 =C2=A0=C2=A0};<br class=3D"">
<br class=3D"">
=C2=A0 =C2=A0=C2=A0template< typename =3D std::make_index_se=
quence<
sizeof ... (elem) > ><br class=3D"">
=C2=A0 =C2=A0=C2=A0struct base;<br class=3D"">
<br class=3D"">
=C2=A0 =C2=A0=C2=A0template< std::size_t ... x ><br class=
=3D"">
=C2=A0 =C2=A0=C2=A0struct base< std::index_sequence< x ..=
.. > ><br
class=3D"">
=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0: tuple_entry< x > ... {=
<br class=3D"">
=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0// Most of the std::tuple impl=
ementation goes here.<br
class=3D"">
=C2=A0 =C2=A0=C2=A0};<br class=3D"">
};<br class=3D"">
<br class=3D"">
template< typename ... elem ><br class=3D"">
struct tuple<br class=3D"">
=C2=A0 =C2=A0=C2=A0: tuple_impl< elem ... >::template bas=
e<> {<br
class=3D"">
=C2=A0 =C2=A0=C2=A0using tuple_impl< elem ... >::template
base<>::base;<br class=3D"">
};</font></div>
<div><font class=3D"" face=3D"Courier"><br class=3D"">
</font></div>
<div><font class=3D"" face=3D"Courier">// test<br class=3D"">
extern tuple< int, char, long > q;<br class=3D"">
char c =3D { q.tuple_entry< 1 >::value }; // no
narrowing =3D> it=C2=A0found the type<br class=3D"">
</font><br class=3D"">
</div>
<div>The complexity here is in forming and using the overload
set at the time <font class=3D"" face=3D"Courier">tuple</font> is
instantiated. Hopefully all the bootstrap stuff (overload set,
etc) gets garbage collected, and what=E2=80=99s left is an ideal =
map
from numbers, through base classes, to types.</div>
</div>
</blockquote>
That's very clever. The recursion is still there---hiding in
amalgam_ftor's abuse of std::common_type ---but at least it only has
to happen once when a instantiating each kind of tuple that way.<br>
<br>
FYI, the code fails to compile with gcc-4.9. <br>
<br>
First problem is minor: struct amalgam has no default constructor
(needed when playing with the type_map decltype stuff). Solution is
to either add "amalgam() =3D default" to the amalgam class definition,
or to use std::declval<> inside the decltype() to obtain an
amalgam instance. <br>
<br>
Second problem is weird: "error: request for member =E2=80=98tuple_entr=
y=E2=80=99 is
ambiguous" (naming tuple_entry<2>, tuple_entry<1>, and
tuple_entry<0> as candidates). Compiles fine with clang-3.6,
so I don't know whether it's a gcc bug or if your code relies on a
clang-ism. I suspect the former since I see no reason why asking for
tuple_entry<1> should consider tuple_entry<0> or
tuple_entry<2> at all, let alone consider them to be
ambiguous.<br>
<br>
Ryan<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------040500010700030203030407--
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 27 Jul 2015 21:11:26 +0800
Raw View
--Apple-Mail=_F20E09AF-83AA-44FE-8550-3A6760EA620E
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9307=E2=80=9327, at 8:40 PM, Ryan Johnson <scovich@gmail.co=
m> wrote:
>=20
> That's very clever. The recursion is still there---hiding in amalgam_ftor=
's abuse of std::common_type ---but at least it only has to happen once whe=
n a instantiating each kind of tuple that way.
Ah, I forgot that part was recursive. It really shouldn=E2=80=99t be; using=
declarations should support pack expansion. Anyway, still, it reduces the =
O(N^2) instantiations that result from applying tuple_element<T,i> over i :=
[0, N) to just O(N) instantiations.
It also shouldn=E2=80=99t be specializing std::common_type, but it works :P=
. The year was 2011, I was naive and carefree=E2=80=A6
> FYI, the code fails to compile with gcc-4.9.=20
>=20
> First problem is minor: struct amalgam has no default constructor (needed=
when playing with the type_map decltype stuff). Solution is to either add =
"amalgam() =3D default" to the amalgam class definition, or to use std::dec=
lval<> inside the decltype() to obtain an amalgam instance.=20
This doesn=E2=80=99t happen with GCC 5.1.
> Second problem is weird: "error: request for member =E2=80=98tuple_entry=
=E2=80=99 is ambiguous" (naming tuple_entry<2>, tuple_entry<1>, and tuple_e=
ntry<0> as candidates). Compiles fine with clang-3.6, so I don't know wheth=
er it's a gcc bug or if your code relies on a clang-ism. I suspect the form=
er since I see no reason why asking for tuple_entry<1> should consider tupl=
e_entry<0> or tuple_entry<2> at all, let alone consider them to be ambiguou=
s.
Hmm, GCC does have a point. The injected-class-names are declared =E2=80=9C=
following the opening brace of the class definition=E2=80=9D which suggests=
that they=E2=80=99re local to each specialization. Perhaps there should be=
a DR; since C++11 it makes more sense for the template-like behavior of in=
jected-class-names to be modeled after alias templates.
Anyway, using a different lookup route fixes it:
template< typename ... elem >
struct tuple
: tuple_impl< elem ... >::template base<> {
typedef tuple_impl< elem ... > impl;
using impl::template base<>::base;
};
extern tuple< int, char, long > q;
char c =3D { q.impl::tuple_entry< 1 >::value };
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_F20E09AF-83AA-44FE-8550-3A6760EA620E
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9307=
=E2=80=9327, at 8:40 PM, Ryan Johnson <<a href=3D"mailto:scovich@gmail.c=
om" class=3D"">scovich@gmail.com</a>> wrote:</div><br class=3D"Apple-int=
erchange-newline"><div class=3D""><span style=3D"font-family: Helvetica; fo=
nt-size: 12px; font-style: normal; font-variant: normal; font-weight: norma=
l; letter-spacing: normal; line-height: normal; orphans: auto; text-align: =
start; text-indent: 0px; text-transform: none; white-space: normal; widows:=
auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color:=
rgb(255, 255, 255); float: none; display: inline !important;" class=3D"">T=
hat's very clever. The recursion is still there---hiding in amalgam_ftor's =
abuse of std::common_type ---but at least it only has to happen once when a=
instantiating each kind of tuple that way.</span><br style=3D"font-family:=
Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font=
-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto=
; text-align: start; text-indent: 0px; text-transform: none; white-space: n=
ormal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; bac=
kground-color: rgb(255, 255, 255);" class=3D""></div></blockquote><div><br =
class=3D""></div><div>Ah, I forgot that part was recursive. It really shoul=
dn=E2=80=99t be; <font face=3D"Courier" class=3D"">using</font> declaration=
s should support pack expansion. Anyway, still, it reduces the O(N^2) insta=
ntiations that result from applying <font face=3D"Courier" class=3D"">=
tuple_element<T,i></font> over i : [0, N) to just O(N) instantiations=
..</div><div><br class=3D""></div><div>It also shouldn=E2=80=99t be speciali=
zing <font face=3D"Courier" class=3D"">std::common_type</font>, but it work=
s :P . The year was 2011, I was naive and carefree=E2=80=A6</div><br class=
=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><span style=3D"f=
ont-family: Helvetica; font-size: 12px; font-style: normal; font-variant: n=
ormal; font-weight: normal; letter-spacing: normal; line-height: normal; or=
phans: auto; text-align: start; text-indent: 0px; text-transform: none; whi=
te-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-widt=
h: 0px; background-color: rgb(255, 255, 255); float: none; display: inline =
!important;" class=3D"">FYI, the code fails to compile with gcc-4.9.<span c=
lass=3D"Apple-converted-space"> </span></span><br style=3D"font-family=
: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; fon=
t-weight: normal; letter-spacing: normal; line-height: normal; orphans: aut=
o; text-align: start; text-indent: 0px; text-transform: none; white-space: =
normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; ba=
ckground-color: rgb(255, 255, 255);" class=3D""><br style=3D"font-family: H=
elvetica; font-size: 12px; font-style: normal; font-variant: normal; font-w=
eight: normal; letter-spacing: normal; line-height: normal; orphans: auto; =
text-align: start; text-indent: 0px; text-transform: none; white-space: nor=
mal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; backg=
round-color: rgb(255, 255, 255);" class=3D""><span style=3D"font-family: He=
lvetica; font-size: 12px; font-style: normal; font-variant: normal; font-we=
ight: normal; letter-spacing: normal; line-height: normal; orphans: auto; t=
ext-align: start; text-indent: 0px; text-transform: none; white-space: norm=
al; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; backgr=
ound-color: rgb(255, 255, 255); float: none; display: inline !important;" c=
lass=3D"">First problem is minor: struct amalgam has no default constructor=
(needed when playing with the type_map decltype stuff). Solution is to eit=
her add "amalgam() =3D default" to the amalgam class definition, or to use =
std::declval<> inside the decltype() to obtain an amalgam instance.<s=
pan class=3D"Apple-converted-space"> </span></span><br style=3D"font-f=
amily: Helvetica; font-size: 12px; font-style: normal; font-variant: normal=
; font-weight: normal; letter-spacing: normal; line-height: normal; orphans=
: auto; text-align: start; text-indent: 0px; text-transform: none; white-sp=
ace: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0p=
x; background-color: rgb(255, 255, 255);" class=3D""></div></blockquote><di=
v><br class=3D""></div><div>This doesn=E2=80=99t happen with GCC 5.1.</div>=
<br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><span s=
tyle=3D"font-family: Helvetica; font-size: 12px; font-style: normal; font-v=
ariant: normal; font-weight: normal; letter-spacing: normal; line-height: n=
ormal; orphans: auto; text-align: start; text-indent: 0px; text-transform: =
none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-st=
roke-width: 0px; background-color: rgb(255, 255, 255); float: none; display=
: inline !important;" class=3D"">Second problem is weird: "error: request f=
or member =E2=80=98tuple_entry=E2=80=99 is ambiguous" (naming tuple_entry&l=
t;2>, tuple_entry<1>, and tuple_entry<0> as candidates). Com=
piles fine with clang-3.6, so I don't know whether it's a gcc bug or if you=
r code relies on a clang-ism. I suspect the former since I see no reason wh=
y asking for tuple_entry<1> should consider tuple_entry<0> or t=
uple_entry<2> at all, let alone consider them to be ambiguous.</span>=
<br style=3D"font-family: Helvetica; font-size: 12px; font-style: normal; f=
ont-variant: normal; font-weight: normal; letter-spacing: normal; line-heig=
ht: normal; orphans: auto; text-align: start; text-indent: 0px; text-transf=
orm: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-te=
xt-stroke-width: 0px; background-color: rgb(255, 255, 255);" class=3D""></d=
iv></blockquote></div><br class=3D""><div class=3D"">Hmm, GCC does have a p=
oint. The injected-class-names are declared =E2=80=9Cfollowing the opening =
brace of the class definition=E2=80=9D which suggests that they=E2=80=99re =
local to each specialization. Perhaps there should be a DR; since C++11 it =
makes more sense for the template-like behavior of injected-class-names to =
be modeled after alias templates.</div><div class=3D""><br class=3D""></div=
><div class=3D"">Anyway, using a different lookup route fixes it:</div><div=
class=3D""><br class=3D""></div><div class=3D""><font face=3D"Courier" cla=
ss=3D"">template< typename ... elem ><br class=3D"">struct tuple<br c=
lass=3D""> : tuple_impl< elem ... >::template base&=
lt;> {<br class=3D""> typedef tuple_impl< elem ... =
> impl;<br class=3D""><br class=3D""> using impl::temp=
late base<>::base;<br class=3D"">};<br class=3D""><br class=3D"">exte=
rn tuple< int, char, long > q;<br class=3D"">char c =3D { q.impl::tup=
le_entry< 1 >::value };<br class=3D""></font><br class=3D""></div></b=
ody></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_F20E09AF-83AA-44FE-8550-3A6760EA620E--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Mon, 27 Jul 2015 07:12:57 -0600
Raw View
This is a multi-part message in MIME format.
--------------020401010801000108030705
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 26/07/2015 12:19 AM, David Krauss wrote:
>
>> On 2015=E2=80=9307=E2=80=9325, at 11:18 PM, Ryan Johnson <scovich@gmail.=
com=20
>> <mailto:scovich@gmail.com>> wrote:
>> The std::indexed_type<Ts,Xs> flavor of magic would be a non-starter,=20
>> though, because there is no machinery in place to detect a "special"=20
>> template class name (which could be obfuscated arbitrarily by use of=20
>> typedefs and template aliases).
>
> Again, indexed_type is an alias template, so it vanishes before=20
> deduction begins. indexed_type and [[pack_index(Xs)]] are one and the=20
> same solution. There=E2=80=99s no class template involved.
The point was that compilers don't have any machinery for detecting=20
"special" template names in that way---whether aliases or classes. The=20
machinery exists---at parse time---to detect an unqualified name (e.g.=20
"sizeof") as a keyword or built-in operator; that happens all the time.=20
That's not the same as checking during semantic analysis whether some=20
qualified name (e.g. std::foo) is somehow special, *especially* in the=20
face of aliases: std::foo could actually be a template alias for=20
something else, or the user could have a "using std::foo" somewhere and=20
give an unqualified name (and they could even have introduced their own=20
templates which would then compete for ADL and cause confusion). Maybe=20
it wouldn't be difficult to add that machinery, but it's definitely not=20
there right now.
>
>>>> This proposal is just trying to eliminate a source of recursion=20
>>>> and/or helper functions that these previous advances don't seem to=20
>>>> have covered. The main messiness that would be left is std::tuple=20
>>>> and std::get, both of which seem pretty difficult to achieve=20
>>>> non-recursively.
>>>
>>> The proposal doesn=E2=80=99t eliminate any template recursion, it elimi=
nates=20
>>> [make_]index_sequence uses and attendant helper template declarations.
>> Using std::make_index_sequence just moves the recursion from the call=20
>> site into library code, which changes nothing from the compiler's=20
>> perspective (see below). That's what I meant when I described it as=20
>> "hiding some kinds of recursion in a library class."
>
> It=E2=80=99s not really the same, since the library-internal helper gets=
=20
> memoized. All the optimizations you found in libc++, for instance,=20
> only matter when first encountering a sequence that=E2=80=99s longer than=
=20
> anything yet seen in the TU.
Fair enough. That's why we have libraries in the first place: for the=20
reuse benefit that comes from factoring out bits of functionality (and=20
the subsequent ability to optimize that functionality once and for all).
It still leaves a lot of boilerplate behind, though.
>> By "hoisting" I meant the use of an unexpanded parameter pack in a=20
>> context where one is not otherwise expected (thank you for helping me=20
>> nail that down with your concise statement). IMO that capability is=20
>> the main feature of N3728. Without the first-class parameter packs=20
>> that N3728 proposes, the notion of an unexpanded parameter pack=20
>> outside any variadic template context---or inside a variadic template=20
>> context, but in an expression that does not mention any of the formal=20
>> parameter packs---is completely foreign.
>
> Disembodied template argument lists, and members that evaluate to pack=20
> expansions, are nothing to sneeze at, either.
True. N3728 go well beyond what your unpack_sequence would demand. But=20
unpack_sequence opens the genie's bottle so to speak, by creating a=20
disembodied parameter pack.
>
>> BTW, even if something like N3728 were accepted, it does not provide=20
>> a clean mechanism for converting a parameter pack into a <size_t...>=20
>> pack, so this proposal would still be useful. It does close an=20
>> important gap, though, by providing a way to define std::tuple=20
>> non-recursively.
>
> N3728 would allow something like
>
> template< std::size_t len >
> std::size_t ... unpack_sequence =3D std::make_index_sequence< len=20
> >::value ...;
>
> An operator to do the same would be redundant.
Interesting point. And as I said early on, if something like N3728 were=20
to improve the situation I'd not complain.
Unfortunately, that proposal looks extremely undercooked at this point.=20
It is sorely lacking in specific details, and I don't think it would=20
actually work to use parameter packs as concepts the way it proposes:
using integral_types =3D <int, char, long, /* etc */>;
auto sum(integral_types... x) { return (... + x); }
Rather than magically selecting one type out of the pack for each=20
argument, the above would attempt to expand to a pack of packs, which=20
would be nonsensical. Unless the proposal specifically adds that=20
magic... but the text seemed to imply that the above was an=20
intuitive/natural consequence of allowing first-class parameter packs.=20
Anyway, I digress...
>
>> I'm not seeing how you could use indexed_type with non-type or=20
>> template template parameter packs. If you still want to pursue it in=20
>> spite of the flaws discussed earlier, could you provide an example?
>
> I don=E2=80=99t plan to pursue it, but the non-type pack would need to ap=
pear=20
> inside a template-id naming a type. For example:
>
> template< int ... i, template< int > class ... tt, std::size_t ... x >
> void f( std::indexed_type< tt< i >, x > ... );
>
>>> If a new keyword is allowed, the best solution is unpack_sequence=20
>>> because it allows you to locally unpack things (even numeric=20
>>> sequences with other pack basis), without introducing any new kind=20
>>> of entity to the language.
>> Eh? It does require a new entity: an unexpanded parameter pack that=20
>> is not part of any enclosing variadic template definition.
>
> Nothing in the language specification requires that unexpanded pack=20
> names must occur inside variadic template declarations. That just=20
> happens to be the only way to get one.
IMO that's splitting hairs: the Standard is---or at least attempts to=20
be---a prescriptive document where behaviors are forbidden unless=20
explicitly stated otherwise.
>
> It=E2=80=99s perhaps a new sort of entity to the implementation, but not =
to=20
> the language.
>
>> While it might be tempting to hack it in quietly for this one (very=20
>> limited) use case, I suspect the Committee would much rather that any=20
>> new entity be fleshed out fully to avoid surprises and ugliness later=20
>> on, when people inevitably try to apply the concept in new and=20
>> unanticipated ways.
>
> What potential complication? The grammar outside templates is the same=20
> as the grammar inside. Non-dependent contexts are usually easier to=20
> process than dependent ones.
Once people see that disembodied parameter packs are allowed, they would=20
want to use them in other ways other than this one extremely limited use=20
case, and be confused/annoyed to learn that they can't. Then comes=20
another proposal to fill the gaps, but it would be constrained by=20
whatever semantics the existing entity already defined.
Constexpr and template variables would be a very good example of this:=20
all sorts of utility and type traits classes (esp. those descending from=20
std::integral_constant) would be cleaned up significantly if changed to=20
constexpr template variables. But that would break backwards=20
compatibility so we'll be stuck with unnecessarily complex code.
>> That said, the unpack_sequence idea *is* tempting because it lets you=20
>> work with subsequences, an ability that __indexof() operator would=20
>> not provide. But I also feel like ability to slice and dice parameter=20
>> packs would be better integrated with N3728 or proposed as a separate=20
>> feature (which would fill the one remaining gap when working with=20
>> tuples, namely how to implement things like std::get and=20
>> std::tuple_element non-recursively).
>
> It seems like the proposals in this thread fall into a spectrum of=20
> degrees of decoupling between the numbers and the pack. indexof is=20
> most tightly coupled because it goes into the pack expansion,=20
> indexed_type is less coupled because it goes into the pack=20
> declaration, and unpack_sequence is least coupled because it goes=20
> anywhere and it only knows about an integral constant expression.
Sure. And each comes with its own warts and benefits.
The indexof operator is kind of nice because it's extremely clear about=20
where those numbers come from, and there's no way to accidentally come=20
up with mismatched parameter packs when trying to use it. That means=20
less cognitive overhead for the user and less complexity for the=20
compiler. At the cost of being very direct and difficult to hide behind=20
a template type.
The unpack_sequence is kind of nice because you don't need an "external"=20
parameter pack at all, which widens the number of use cases it can help=20
with. At the cost of introducing a new concept to the language in an=20
incomplete way.
Ryan
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------020401010801000108030705
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 26/07/2015 12:19 AM, David Krauss
wrote:<br>
</div>
<blockquote
cite=3D"mid:EE639833-AAC0-4FE7-B015-8A2A3012DB15@gmail.com"
type=3D"cite">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8">
<br class=3D"">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">On 2015=E2=80=9307=E2=80=9325, at 11:18 PM, Ryan =
Johnson <<a
moz-do-not-send=3D"true" href=3D"mailto:scovich@gmail.com"
class=3D"">scovich@gmail.com</a>> wrote:</div>
The std::indexed_type<Ts,Xs> flavor of magic would be a
non-starter, though, because there is no machinery in place to
detect a "special" template class name (which could be
obfuscated arbitrarily by use of typedefs and template
aliases). <br class=3D"">
</blockquote>
<div><br class=3D"">
</div>
<div>Again, <font class=3D"" face=3D"Courier">indexed_type</font>
is an alias template, so it vanishes before deduction begins.
<font class=3D"" face=3D"Courier">indexed_type</font> and <font
class=3D"" face=3D"Courier">[[pack_index(Xs)]]</font> are one
and the same solution. There=E2=80=99s no class template involved=
..</div>
</div>
</blockquote>
<br>
The point was that compilers don't have any machinery for detecting
"special" template names in that way---whether aliases or classes.
The machinery exists---at parse time---to detect an unqualified name
(e.g. "sizeof") as a keyword or built-in operator; that happens all
the time. That's not the same as checking during semantic analysis
whether some qualified name (e.g. std::foo) is somehow special,
*especially* in the face of aliases: std::foo could actually be a
template alias for something else, or the user could have a "using
std::foo" somewhere and give an unqualified name (and they could
even have introduced their own templates which would then compete
for ADL and cause confusion). Maybe it wouldn't be difficult to add
that machinery, but it's definitely not there right now. <br>
<br>
<blockquote
cite=3D"mid:EE639833-AAC0-4FE7-B015-8A2A3012DB15@gmail.com"
type=3D"cite">
<div>
<div><br class=3D"">
</div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<blockquote
cite=3D"mid:FBD72BF1-5E44-4B4E-90EA-3F726445819F@gmail.com"
type=3D"cite" class=3D"">
<div class=3D"">
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">=
This
proposal is just trying to eliminate a source of
recursion and/or helper functions that these
previous advances don't seem to have covered.
The main messiness that would be left is
std::tuple and std::get, both of which seem
pretty difficult to achieve non-recursively.<br
class=3D"">
</div>
</div>
</blockquote>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">The proposal doesn=E2=80=99t eliminate an=
y
template recursion, it eliminates [<font class=3D""
face=3D"Courier">make_</font>]<font class=3D""
face=3D"Courier">index_sequence</font> uses and
attendant helper template declarations. </div>
</div>
</blockquote>
Using std::make_index_sequence just moves the recursion
from the call site into library code, which changes
nothing from the compiler's perspective (see below).
That's what I meant when I described it as "hiding some
kinds of recursion in a library class." <br class=3D"">
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>It=E2=80=99s not really the same, since the library-internal h=
elper
gets memoized. All the optimizations you found in libc++, for
instance, only matter when first encountering a sequence
that=E2=80=99s longer than anything yet=C2=A0seen in the TU.</div=
>
</div>
</blockquote>
Fair enough. That's why we have libraries in the first place: for
the reuse benefit that comes from factoring out bits of
functionality (and the subsequent ability to optimize that
functionality once and for all). <br>
<br>
It still leaves a lot of boilerplate behind, though.<br>
<br class=3D"">
<blockquote
cite=3D"mid:EE639833-AAC0-4FE7-B015-8A2A3012DB15@gmail.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D""> By
"hoisting" I meant the use of an unexpanded parameter pack
in a context where one is not otherwise expected (thank
you for helping me nail that down with your concise
statement). IMO that capability is the main feature of
N3728. Without the first-class parameter packs that N3728
proposes, the notion of an unexpanded parameter pack
outside any variadic template context---or inside a
variadic template context, but in an expression that does
not mention any of the formal parameter packs---is
completely foreign.<br class=3D"">
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>Disembodied template argument lists, and members that
evaluate to pack expansions, are nothing to sneeze at, either.</d=
iv>
</div>
</blockquote>
True. N3728 go well beyond what your unpack_sequence would demand.
But unpack_sequence opens the genie's bottle so to speak, by
creating a disembodied parameter pack. <br>
<br>
<blockquote
cite=3D"mid:EE639833-AAC0-4FE7-B015-8A2A3012DB15@gmail.com"
type=3D"cite">
<div><br class=3D"">
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">BTW, even =
if
something like N3728 were accepted, it does not provide a
clean mechanism for converting a parameter pack into a
<size_t...> pack, so this proposal would still be
useful. It does close an important gap, though, by
providing a way to define std::tuple non-recursively. <br
class=3D"">
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>N3728 would allow something like</div>
<div><br class=3D"">
</div>
<div><font class=3D"" face=3D"Courier">template< std::size_t len
></font></div>
<div><font class=3D"" face=3D"Courier">std::size_t ...
unpack_sequence =3D std::make_index_sequence< len
>::value ...;</font></div>
<div><br class=3D"">
</div>
<div>An operator to do the same would be redundant.</div>
</div>
</blockquote>
Interesting point. And as I said early on, if something like N3728
were to improve the situation I'd not complain. <br>
<br>
Unfortunately, that proposal looks extremely undercooked at this
point. It is sorely lacking in specific details, and I don't think
it would actually work to use parameter packs as concepts the way it
proposes:<br>
<br>
<tt>using integral_types =3D <int, char, long, /* etc */>;</tt><t=
t><br>
</tt><tt>auto sum(integral_types... x) { return (... + x); }</tt><tt><b=
r>
</tt><br>
Rather than magically selecting one type out of the pack for each
argument, the above would attempt to expand to a pack of packs,
which would be nonsensical. Unless the proposal specifically adds
that magic... but the text seemed to imply that the above was an
intuitive/natural consequence of allowing first-class parameter
packs. Anyway, I digress...<br>
<br>
<br>
<blockquote
cite=3D"mid:EE639833-AAC0-4FE7-B015-8A2A3012DB15@gmail.com"
type=3D"cite">
<div><br class=3D"">
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">I'm not
seeing how you could use indexed_type with non-type or
template template parameter packs. If you still want to
pursue it in spite of the flaws discussed earlier, could
you provide an example? <br class=3D"">
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>I don=E2=80=99t plan to pursue it, but the non-type pack would=
need
to appear inside a template-id naming a type. For example:</div>
<div><br class=3D"">
</div>
<div><font class=3D"" face=3D"Courier">template< int ... i,
template< int > class ... tt, std::size_t ... x ></fon=
t></div>
<div><font class=3D"" face=3D"Courier">void f( std::indexed_type<=
;
tt< i >, x > ... );</font></div>
<br class=3D"">
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<blockquote
cite=3D"mid:FBD72BF1-5E44-4B4E-90EA-3F726445819F@gmail.com"
type=3D"cite" class=3D"">
<div class=3D"">If a new keyword is allowed, the best
solution is <font class=3D"" face=3D"Courier">unpack_sequ=
ence</font>
because it allows you to locally unpack things (even
numeric sequences with other pack basis), without
introducing any new kind of entity to the language.</div>
</blockquote>
Eh? It does require a new entity: an unexpanded parameter
pack that is not part of any enclosing variadic template
definition. </div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>Nothing in the language specification requires that
unexpanded pack names must occur inside variadic template
declarations. That just happens to be the only way to get one.</d=
iv>
</div>
</blockquote>
IMO that's splitting hairs: the Standard is---or at least attempts
to be---a prescriptive document where behaviors are forbidden unless
explicitly stated otherwise. <br>
<br>
<blockquote
cite=3D"mid:EE639833-AAC0-4FE7-B015-8A2A3012DB15@gmail.com"
type=3D"cite">
<div>
<div><br class=3D"">
</div>
<div>It=E2=80=99s perhaps a new sort of entity to the implementatio=
n,
but not to the language.</div>
<br class=3D"">
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">While it
might be tempting to hack it in quietly for this one (very
limited) use case, I suspect the Committee would much
rather that any new entity be fleshed out fully to avoid
surprises and ugliness later on, when people inevitably
try to apply the concept in new and unanticipated ways. <br
class=3D"">
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>What potential complication? The grammar outside templates
is the same as the grammar inside. Non-dependent contexts are
usually easier=C2=A0to process than dependent ones.</div>
</div>
</blockquote>
Once people see that disembodied parameter packs are allowed, they
would want to use them in other ways other than this one extremely
limited use case, and be confused/annoyed to learn that they can't.
Then comes another proposal to fill the gaps, but it would be
constrained by whatever semantics the existing entity already
defined. <br>
<br>
Constexpr and template variables would be a very good example of
this: all sorts of utility and type traits classes (esp. those
descending from std::integral_constant) would be cleaned up
significantly if changed to constexpr template variables. But that
would break backwards compatibility so we'll be stuck with
unnecessarily complex code.<br>
<br class=3D"">
<blockquote
cite=3D"mid:EE639833-AAC0-4FE7-B015-8A2A3012DB15@gmail.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">That said,
the unpack_sequence idea *is* tempting because it lets you
work with subsequences, an ability that __indexof()
operator would not provide. But I also feel like ability
to slice and dice parameter packs would be better
integrated with N3728 or proposed as a separate feature
(which would fill the one remaining gap when working with
tuples, namely how to implement things like std::get and
std::tuple_element non-recursively). <br class=3D"">
</div>
</div>
</blockquote>
<br class=3D"">
</div>
<div>It seems like the proposals in this thread fall into a
spectrum of degrees of decoupling between the numbers and the
pack. <font class=3D"" face=3D"Courier">indexof</font> is most
tightly coupled because it goes into the pack expansion, <font
class=3D"" face=3D"Courier">indexed_type</font> is less coupled
because it goes into the pack declaration, and <font class=3D""
face=3D"Courier">unpack_sequence</font> is least coupled because
it goes anywhere and it only knows about an integral constant
expression.</div>
</blockquote>
Sure. And each comes with its own warts and benefits. <br>
<br>
The indexof operator is kind of nice because it's extremely clear
about where those numbers come from, and there's no way to
accidentally come up with mismatched parameter packs when trying to
use it. That means less cognitive overhead for the user and less
complexity for the compiler. At the cost of being very direct and
difficult to hide behind a template type. <br>
<br>
The unpack_sequence is kind of nice because you don't need an
"external" parameter pack at all, which widens the number of use
cases it can help with. At the cost of introducing a new concept to
the language in an incomplete way. <br>
<br>
Ryan<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------020401010801000108030705--
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 27 Jul 2015 21:15:19 +0800
Raw View
--Apple-Mail=_40439F09-6C7E-43D9-AA8E-7C13FA654AAE
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9307=E2=80=9327, at 9:11 PM, David Krauss <potswa@gmail.com=
> wrote:
>=20
> Perhaps there should be a DR; since C++11 it makes more sense for the tem=
plate-like behavior of injected-class-names to be modeled after alias templ=
ates.
On second thought, that doesn=E2=80=99t help. The template-name of each nes=
ted alias template would still be unique to its class. It=E2=80=99s a Clang=
bug.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_40439F09-6C7E-43D9-AA8E-7C13FA654AAE
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9307=
=E2=80=9327, at 9:11 PM, David Krauss <<a href=3D"mailto:potswa@gmail.co=
m" class=3D"">potswa@gmail.com</a>> wrote:</div><br class=3D"Apple-inter=
change-newline"><div class=3D""><span style=3D"font-family: Helvetica; font=
-size: 12px; font-style: normal; font-variant: normal; font-weight: normal;=
letter-spacing: normal; line-height: normal; orphans: auto; text-align: st=
art; text-indent: 0px; text-transform: none; white-space: normal; widows: a=
uto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; displa=
y: inline !important;" class=3D"">Perhaps there should be a DR; since C++11=
it makes more sense for the template-like behavior of injected-class-names=
to be modeled after alias templates.</span></div></blockquote></div><br cl=
ass=3D""><div class=3D"">On second thought, that doesn=E2=80=99t help. The =
template-name of each nested alias template would still be unique to its cl=
ass. It=E2=80=99s a Clang bug.</div><div class=3D""><br class=3D""></div></=
body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_40439F09-6C7E-43D9-AA8E-7C13FA654AAE--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Mon, 27 Jul 2015 07:20:44 -0600
Raw View
This is a multi-part message in MIME format.
--------------090303030707040709040401
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 27/07/2015 7:11 AM, David Krauss wrote:
>
>> On 2015=E2=80=9307=E2=80=9327, at 8:40 PM, Ryan Johnson <scovich@gmail.c=
om=20
>> <mailto:scovich@gmail.com>> wrote:
>>
>> That's very clever. The recursion is still there---hiding in=20
>> amalgam_ftor's abuse of std::common_type ---but at least it only has=20
>> to happen once when a instantiating each kind of tuple that way.
>
> Ah, I forgot that part was recursive. It really shouldn=E2=80=99t be; usi=
ng=20
> declarations should support pack expansion. Anyway, still, it reduces=20
> the O(N^2) instantiations that result from applying tuple_element<T,i>=20
> over i : [0, N) to just O(N) instantiations.
100% agree, on both counts.
> It also shouldn=E2=80=99t be specializing std::common_type, but it works =
:P .=20
> The year was 2011, I was naive and carefree=E2=80=A6
That one definitely makes you want to wash your hands after looking at=20
it... but if it works and the alternatives are vastly more hairy, I'd go=20
for the dirty hack any time.
Ryan
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------090303030707040709040401
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 27/07/2015 7:11 AM, David Krauss
wrote:<br>
</div>
<blockquote
cite=3D"mid:E6BAFA76-93A4-42A4-91FF-4751036049EE@gmail.com"
type=3D"cite">
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf=
-8">
<br class=3D"">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">On 2015=E2=80=9307=E2=80=9327, at 8:40 PM, Ryan J=
ohnson <<a
moz-do-not-send=3D"true" href=3D"mailto:scovich@gmail.com"
class=3D"">scovich@gmail.com</a>> wrote:</div>
<br class=3D"Apple-interchange-newline">
<div class=3D""><span style=3D"font-family: Helvetica; font-size:
12px; font-style: normal; font-variant: normal;
font-weight: normal; letter-spacing: normal; line-height:
normal; orphans: auto; text-align: start; text-indent:
0px; text-transform: none; white-space: normal; widows:
auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;
background-color: rgb(255, 255, 255); float: none;
display: inline !important;" class=3D"">That's very clever.
The recursion is still there---hiding in amalgam_ftor's
abuse of std::common_type ---but at least it only has to
happen once when a instantiating each kind of tuple that
way.</span><br style=3D"font-family: Helvetica; font-size:
12px; font-style: normal; font-variant: normal;
font-weight: normal; letter-spacing: normal; line-height:
normal; orphans: auto; text-align: start; text-indent:
0px; text-transform: none; white-space: normal; widows:
auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;
background-color: rgb(255, 255, 255);" class=3D"">
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>Ah, I forgot that part was recursive. It really shouldn=E2=80=
=99t
be; <font class=3D"" face=3D"Courier">using</font> declarations
should support pack expansion. Anyway, still, it reduces the
O(N^2) instantiations that result from applying=C2=A0<font class=
=3D""
face=3D"Courier">tuple_element<T,i></font> over i : [0,
N) to just O(N) instantiations.</div>
</div>
</blockquote>
100% agree, on both counts. <br>
<br>
<blockquote
cite=3D"mid:E6BAFA76-93A4-42A4-91FF-4751036049EE@gmail.com"
type=3D"cite">
<div>
<div>It also shouldn=E2=80=99t be specializing <font class=3D""
face=3D"Courier">std::common_type</font>, but it works :P .
The year was 2011, I was naive and carefree=E2=80=A6</div>
</div>
</blockquote>
That one definitely makes you want to wash your hands after looking
at it... but if it works and the alternatives are vastly more hairy,
I'd go for the dirty hack any time.<br>
<br>
Ryan<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------090303030707040709040401--
.
Author: David Krauss <potswa@gmail.com>
Date: Mon, 27 Jul 2015 23:20:54 +0800
Raw View
--Apple-Mail=_5B63D2F1-A615-4453-9506-B96E25E1E570
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9307=E2=80=9327, at 9:12 PM, Ryan Johnson <scovich@gmail.co=
m> wrote:
>=20
> The point was that compilers don't have any machinery for detecting "spec=
ial" template names in that way---whether aliases or classes.
There=E2=80=99s nothing special about the alias that needs to be detected. =
The alias specialization gets converted to a dependent attribute before the=
=E2=80=9Cdetection=E2=80=9D step =E2=80=94 deduction =E2=80=94 begins.
The point is moot, so maybe we should give it a rest.
>> Disembodied template argument lists, and members that evaluate to pack e=
xpansions, are nothing to sneeze at, either.
> True. N3728 go well beyond what your unpack_sequence would demand. But un=
pack_sequence opens the genie's bottle so to speak, by creating a disembodi=
ed parameter pack.=20
N3728 proposes disembodied argument list syntax like typedef <int, short, v=
oid> ts. That=E2=80=99s different from unpack_sequence(N) which is an ordin=
ary pack, but potentially in a non-template context.
> Once people see that disembodied parameter packs are allowed, they would =
want to use them in other ways other than this one extremely limited use ca=
se, and be confused/annoyed to learn that they can't. Then comes another pr=
oposal to fill the gaps, but it would be constrained by whatever semantics =
the existing entity already defined.=20
This is a slippery slope argument. But it goes further: if you can define y=
our own freestanding sequence of types, why not a sequence of templates or =
values? When should you use a compile-time value sequence as opposed to a c=
onstexpr array or initializer_list? What about mixed argument lists; should=
n=E2=80=99t <int, 3, std::tuple> be supported if <int, short, void> is?
unpack_sequence generates a pack of values, but N3728 actually only address=
es types. The library implementation I suggested earlier was a bit of extra=
polation. As you said, N3728 isn=E2=80=99t fully cooked. As a result, we te=
nd to use it as a blank canvas. That can generate a false sense of consensu=
s.
A single, minimal operator avoids all that. If there are so many orthogonal=
directions down the slippery slope, that=E2=80=99s in itself an argument t=
o stay at the top.
> Constexpr and template variables would be a very good example of this: al=
l sorts of utility and type traits classes (esp. those descending from std:=
:integral_constant) would be cleaned up significantly if changed to constex=
pr template variables. But that would break backwards compatibility so we'l=
l be stuck with unnecessarily complex code.
C++14 does have the _v suffix.
> The indexof operator is kind of nice because it's extremely clear about w=
here those numbers come from, and there's no way to accidentally come up wi=
th mismatched parameter packs when trying to use it. That means less cognit=
ive overhead for the user and less complexity for the compiler. At the cost=
of being very direct and difficult to hide behind a template type.=20
>=20
> The unpack_sequence is kind of nice because you don't need an "external" =
parameter pack at all, which widens the number of use cases it can help wit=
h. At the cost of introducing a new concept to the language in an incomplet=
e way.=20
Fair assessment.
unpack_sequence is a bit verbose in its own way, but it potentially saves t=
he effort of making any template declaration in the first place. It would b=
e nice to see an apples to apples comparison between indexof and unpack_seq=
uence.
My guess is that the committee would prefer to see all these proposals pres=
ented side-by-side and working through identical example problems.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_5B63D2F1-A615-4453-9506-B96E25E1E570
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9307=
=E2=80=9327, at 9:12 PM, Ryan Johnson <<a href=3D"mailto:scovich@gmail.c=
om" class=3D"">scovich@gmail.com</a>> wrote:</div><br class=3D"Apple-int=
erchange-newline"><div class=3D"">
=20
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
" class=3D"">
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<div class=3D"moz-cite-prefix">The point was that compilers don't have =
any machinery for detecting
"special" template names in that way---whether aliases or classes.</div=
></div></div></blockquote><div><br class=3D""></div><div>There=E2=80=99s no=
thing special about the alias that needs to be detected. The alias speciali=
zation gets converted to a dependent attribute before the =E2=80=9Cdetectio=
n=E2=80=9D step =E2=80=94 deduction =E2=80=94 begins.</div><div><br class=
=3D""></div><div>The point is moot, so maybe we should give it a rest.</div=
><br class=3D""><blockquote type=3D"cite" class=3D""><div class=3D""><div b=
gcolor=3D"#FFFFFF" text=3D"#000000" class=3D""><blockquote cite=3D"mid:EE63=
9833-AAC0-4FE7-B015-8A2A3012DB15@gmail.com" type=3D"cite" class=3D""><div c=
lass=3D""><div class=3D"">Disembodied template argument lists, and members =
that
evaluate to pack expansions, are nothing to sneeze at, either.</d=
iv>
</div>
</blockquote>
True. N3728 go well beyond what your unpack_sequence would demand.
But unpack_sequence opens the genie's bottle so to speak, by
creating a disembodied parameter pack. <br class=3D""></div></div></blo=
ckquote><div><br class=3D""></div><div>N3728 proposes disembodied argument =
list syntax like <font face=3D"Courier" class=3D"">typedef <int, short, =
void> ts</font>. That=E2=80=99s different from <font face=3D"Courier" cl=
ass=3D"">unpack_sequence(N)</font> which is an ordinary pack, but potential=
ly in a non-template context.</div><div><br class=3D""></div><blockquote ty=
pe=3D"cite" class=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#00=
0000" class=3D"">
=20
Once people see that disembodied parameter packs are allowed, they
would want to use them in other ways other than this one extremely
limited use case, and be confused/annoyed to learn that they can't.
Then comes another proposal to fill the gaps, but it would be
constrained by whatever semantics the existing entity already
defined. <br class=3D""></div></div></blockquote><div><br class=3D""></=
div><div>This is a slippery slope argument. But it goes further: if you can=
define your own freestanding sequence of types, why not a sequence of temp=
lates or values? When should you use a compile-time value sequence as oppos=
ed to a constexpr array or <font face=3D"Courier" class=3D"">initializer_li=
st</font>? What about mixed argument lists; shouldn=E2=80=99t <font face=3D=
"Courier" class=3D""><int, 3, std::tuple></font> be supported if=
<font face=3D"Courier" class=3D""><int, short, void></font> is?</div=
><div><br class=3D""></div><div><font face=3D"Courier" class=3D"">unpack_se=
quence</font> generates a pack of values, but N3728 actually only addresses=
types. The library implementation I suggested earlier was a bit of extrapo=
lation. As you said, N3728 isn=E2=80=99t fully cooked. As a result, we tend=
to use it as a blank canvas. That can generate a false sense of consensus.=
</div><div><br class=3D""></div><div>A single, minimal operator avoids all =
that. If there are so many orthogonal directions down the slippery slope, t=
hat=E2=80=99s in itself an argument to stay at the top.</div><br class=3D""=
><blockquote type=3D"cite" class=3D""><div class=3D""><div bgcolor=3D"#FFFF=
FF" text=3D"#000000" class=3D"">Constexpr and template variables would be a=
very good example of
this: all sorts of utility and type traits classes (esp. those
descending from std::integral_constant) would be cleaned up
significantly if changed to constexpr template variables. But that
would break backwards compatibility so we'll be stuck with
unnecessarily complex code.<br class=3D""></div></div></blockquote><div=
><br class=3D""></div><div>C++14 does have the <font face=3D"Courier" class=
=3D"">_v</font> suffix.</div><br class=3D""><blockquote type=3D"cite" class=
=3D""><div class=3D""><div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">=
The indexof operator is kind of nice because it's extremely clear
about where those numbers come from, and there's no way to
accidentally come up with mismatched parameter packs when trying to
use it. That means less cognitive overhead for the user and less
complexity for the compiler. At the cost of being very direct and
difficult to hide behind a template type. <br class=3D"">
<br class=3D"">
The unpack_sequence is kind of nice because you don't need an
"external" parameter pack at all, which widens the number of use
cases it can help with. At the cost of introducing a new concept to
the language in an incomplete way. <br class=3D""></div></div></blockqu=
ote><br class=3D""></div><div>Fair assessment.</div><br class=3D""><div cla=
ss=3D""><font face=3D"Courier" class=3D"">unpack_sequence</font> is a bit v=
erbose in its own way, but it potentially saves the effort of making any te=
mplate declaration in the first place. It would be nice to see an apples to=
apples comparison between <font face=3D"Courier" class=3D"">indexof</font>=
and <font face=3D"Courier" class=3D"">unpack_sequence</font>.</div><div cl=
ass=3D""><br class=3D""></div><div class=3D"">My guess is that the committe=
e would prefer to see all these proposals presented side-by-side and workin=
g through identical example problems.</div><div class=3D""><br class=3D""><=
/div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_5B63D2F1-A615-4453-9506-B96E25E1E570--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Mon, 27 Jul 2015 12:00:50 -0600
Raw View
This is a multi-part message in MIME format.
--------------050505060703020302060207
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 27/07/2015 9:20 AM, David Krauss wrote:
>>> Disembodied template argument lists, and members that evaluate to=20
>>> pack expansions, are nothing to sneeze at, either.
>> True. N3728 go well beyond what your unpack_sequence would demand.=20
>> But unpack_sequence opens the genie's bottle so to speak, by creating=20
>> a disembodied parameter pack.
>
> N3728 proposes disembodied argument list syntax like typedef <int,=20
> short, void> ts. That=E2=80=99s different from unpack_sequence(N) which i=
s an=20
> ordinary pack, but potentially in a non-template context.
You actually make a very good point that N3728 only addresses types, not=20
integer sequences, and so is orthogonal in that respect. I also suspect=20
strongly that N3728 will not mature in time for C++17, so let's drop it=20
from the discussion and focus on stand-alone solutions to the problem at=20
hand.
>> Constexpr and template variables would be a very good example of=20
>> this: all sorts of utility and type traits classes (esp. those=20
>> descending from std::integral_constant) would be cleaned up=20
>> significantly if changed to constexpr template variables. But that=20
>> would break backwards compatibility so we'll be stuck with=20
>> unnecessarily complex code.
>
> C++14 does have the _v suffix.
>
Definitely better than nothing, but still a hack to paper over the=20
backwards compatibility issue. Anyway, there's nothing to be done for=20
it. The language evolved in a way that would have been difficult to=20
predict (or at least define precisely) up front, and this is the result.
>> The indexof operator is kind of nice because it's extremely clear=20
>> about where those numbers come from, and there's no way to=20
>> accidentally come up with mismatched parameter packs when trying to=20
>> use it. That means less cognitive overhead for the user and less=20
>> complexity for the compiler. At the cost of being very direct and=20
>> difficult to hide behind a template type.
>>
>> The unpack_sequence is kind of nice because you don't need an=20
>> "external" parameter pack at all, which widens the number of use=20
>> cases it can help with. At the cost of introducing a new concept to=20
>> the language in an incomplete way.
>
> Fair assessment.
>
> unpack_sequence is a bit verbose in its own way, but it potentially=20
> saves the effort of making any template declaration in the first=20
> place. It would be nice to see an apples to apples comparison between=20
> indexof and unpack_sequence.
>
> My guess is that the committee would prefer to see all these proposals=20
> presented side-by-side and working through identical example problems.
You're probably right. I'll have to dive back into clang when I get a=20
chance, to get a sense of how easy or difficult it would be to implement=20
unpack_sequence.
We agree that those two are the only viable candidates that have come up=20
so far?
A follow-up question about unpack_sequence(): should it always take a=20
constexpr size_t as its argument? Or should it also accept a parameter=20
pack, for cases where you have one handy already? E.g.:
template <typename... Ts>
int hash(std::tuple<Ts...> const &tup)
{
using std::hash; // ADL
return (... ^ hash(std::get<unpack_sequence(Ts)>(tup)));
}
That would make it a superset of the __indexof() operator I implemented=20
already, and avoid the need for boilerplate like=20
unpack_sequence(sizeof...(Ts)). Though perhaps it's best to present the=20
two fully independently, and let the Committee hash out any potential=20
convergence of the two.
Actually, I should also throw in one idea I've considered but not had=20
time to pursue:
Based on clang's internals, it should be relatively easy to define a=20
slightly modified operator, call it __unsafe_spooky_pack_indexof(T) that=20
returns the parser's current pack expansion index regardless of whether=20
T itself is actually a parameter pack. This would be spooky black magic=20
of the worst kind (and I couldn't say whether it could be easily=20
implemented in another compiler), but it would allow:
namespace std
{
template <typename T, size_t N=3D__unsafe_spooky_pack_indexof(T)>
constexpr size_t const indexof =3D N;
}
template <typename... Ts>
int hash(std::tuple<Ts...> const &tup)
{
using std::hash; // ADL
return (... ^ hash(std::get<std::indexof<Ts>>(tup)));
}
The long, scary name should discourage use of the operator outside the=20
intended library implementation, and use of std::indexof<T> with any T=20
not directly expanded from a parameter pack would invoke undefined=20
behavior (no diagnostic, because the rules of template instantiation=20
would make it difficult for the compiler to detect improper use). In=20
particular:
template <typename T>
struct foo { static constexpr size_t const N =3D std::indexof<T>; };
// undefined behavior
template <typename T>
constexpr size_t const bar =3D std::indexof<T>;
// undefined behavior
template <typename T>
using baz =3D std::indexof<T>;
// iffy but probably well-defined anywhere std::indexof would be=20
well-defined
Behavior of std::indexof<T, N> (with user-supplied N) is perfectly=20
well-defined because that would sidestep the spooky/unsafe default value=20
computation. It would also be perfectly useless, unless you happened to=20
need a mapping from types to size_t in some other context, and were=20
willing to set it up manually.
I'm torn: namespace std is much less crowded than the global namespace,=20
so std::indexof is more likely to be available than a new indexof=20
keyword. But the __indexof() operator is much safer because improper=20
uses fail to compile.
Thoughts?
Ryan
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------050505060703020302060207
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 27/07/2015 9:20 AM, David Krauss
wrote:<br>
</div>
<blockquote
cite=3D"mid:65703E36-1568-4FF9-99B6-E98FDD6C02EF@gmail.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">
<blockquote
cite=3D"mid:EE639833-AAC0-4FE7-B015-8A2A3012DB15@gmail.com"
type=3D"cite" class=3D"">
<div class=3D"">
<div class=3D"">Disembodied template argument lists, and
members that evaluate to pack expansions, are
nothing to sneeze at, either.</div>
</div>
</blockquote>
True. N3728 go well beyond what your unpack_sequence would
demand. But unpack_sequence opens the genie's bottle so to
speak, by creating a disembodied parameter pack. <br
class=3D"">
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>N3728 proposes disembodied argument list syntax like <font
class=3D"" face=3D"Courier">typedef <int, short, void> ts=
</font>.
That=E2=80=99s different from <font class=3D"" face=3D"Courier">u=
npack_sequence(N)</font>
which is an ordinary pack, but potentially in a non-template
context.</div>
</div>
</blockquote>
You actually make a very good point that N3728 only addresses types,
not integer sequences, and so is orthogonal in that respect. I also
suspect strongly that N3728 will not mature in time for C++17, so
let's drop it from the discussion and focus on stand-alone solutions
to the problem at hand. <br>
<br class=3D"">
<blockquote
cite=3D"mid:65703E36-1568-4FF9-99B6-E98FDD6C02EF@gmail.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">Constexpr =
and
template variables would be a very good example of this:
all sorts of utility and type traits classes (esp. those
descending from std::integral_constant) would be cleaned
up significantly if changed to constexpr template
variables. But that would break backwards compatibility so
we'll be stuck with unnecessarily complex code.<br
class=3D"">
</div>
</div>
</blockquote>
<div><br class=3D"">
</div>
<div>C++14 does have the <font class=3D"" face=3D"Courier">_v</font=
>
suffix.</div>
</div>
<br class=3D"">
</blockquote>
Definitely better than nothing, but still a hack to paper over the
backwards compatibility issue. Anyway, there's nothing to be done
for it. The language evolved in a way that would have been difficult
to predict (or at least define precisely) up front, and this is the
result. <br>
<br class=3D"">
<blockquote
cite=3D"mid:65703E36-1568-4FF9-99B6-E98FDD6C02EF@gmail.com"
type=3D"cite">
<div>
<blockquote type=3D"cite" class=3D"">
<div class=3D"">
<div bgcolor=3D"#FFFFFF" text=3D"#000000" class=3D"">The indexo=
f
operator is kind of nice because it's extremely clear
about where those numbers come from, and there's no way to
accidentally come up with mismatched parameter packs when
trying to use it. That means less cognitive overhead for
the user and less complexity for the compiler. At the cost
of being very direct and difficult to hide behind a
template type. <br class=3D"">
<br class=3D"">
The unpack_sequence is kind of nice because you don't need
an "external" parameter pack at all, which widens the
number of use cases it can help with. At the cost of
introducing a new concept to the language in an incomplete
way. <br class=3D"">
</div>
</div>
</blockquote>
<br class=3D"">
</div>
<div>Fair assessment.</div>
<br class=3D"">
<div class=3D""><font class=3D"" face=3D"Courier">unpack_sequence</fo=
nt>
is a bit verbose in its own way, but it potentially saves the
effort of making any template declaration in the first place. It
would be nice to see an apples to apples comparison between <font
class=3D"" face=3D"Courier">indexof</font> and <font class=3D""
face=3D"Courier">unpack_sequence</font>.</div>
<div class=3D""><br class=3D"">
</div>
<div class=3D"">My guess is that the committee would prefer to see
all these proposals presented side-by-side and working through
identical example problems.</div>
</blockquote>
You're probably right. I'll have to dive back into clang when I get
a chance, to get a sense of how easy or difficult it would be to
implement unpack_sequence. <br>
<br>
We agree that those two are the only viable candidates that have
come up so far? <br>
<br>
A follow-up question about unpack_sequence(): should it always take
a constexpr size_t as its argument? Or should it also accept a
parameter pack, for cases where you have one handy already? E.g.:<br>
<tt><br>
</tt><tt>template <typename... Ts></tt><tt><br>
</tt><tt>int hash(std::tuple<Ts...> const &tup) </tt><tt><br>
</tt><tt>{</tt><tt><br>
</tt><tt>=C2=A0=C2=A0 using std::hash; // ADL</tt><tt><br>
</tt><tt>=C2=A0=C2=A0 return (... ^
hash(std::get<unpack_sequence(Ts)>(tup)));</tt><tt><br>
</tt><tt>}</tt><tt><br>
</tt><br>
That would make it a superset of the <tt>__indexof()</tt> operator
I implemented already, and avoid the need for boilerplate like <tt>unpa=
ck_sequence(sizeof...(Ts))</tt>.
Though perhaps it's best to present the two fully independently, and
let the Committee hash out any potential convergence of the two. <br>
<br>
Actually, I should also throw in one idea I've considered but not
had time to pursue:<br>
<br>
Based on clang's internals, it should be relatively easy to define a
slightly modified operator, call it <tt>__unsafe_spooky_pack_indexof(T)=
</tt>
that returns the parser's current pack expansion index regardless of
whether T itself is actually a parameter pack. This would be spooky
black magic of the worst kind (and I couldn't say whether it could
be easily implemented in another compiler), but it would allow:<br>
<br>
<tt>namespace std </tt><tt><br>
</tt><tt>{</tt><tt><br>
</tt><tt>
template <typename T, size_t
N=3D__unsafe_spooky_pack_indexof(T)></tt><tt><br>
</tt><tt>constexpr size_t const indexof =3D N;</tt><tt><br>
</tt><tt>
}</tt><tt><br>
</tt><tt>
</tt><tt><br>
</tt><tt>template <typename... Ts></tt><tt><br>
</tt><tt>int hash(std::tuple<Ts...> const &tup) </tt><tt><br>
</tt><tt>{</tt><tt><br>
</tt><tt>=C2=A0=C2=A0 using std::hash; // ADL</tt><tt><br>
</tt><tt>=C2=A0=C2=A0 return (... ^ hash(std::get<std::indexof<Ts=
>>(tup)));</tt><tt><br>
</tt><tt>}</tt><tt><br>
<br>
</tt>The long, scary name should discourage use of the operator
outside the intended library implementation, and use of
std::indexof<T> with any T not directly expanded from a
parameter pack would invoke undefined behavior (no diagnostic,
because the rules of template instantiation would make it difficult
for the compiler to detect improper use). In particular:<br>
<br>
<tt>template <typename T></tt><tt><br>
</tt><tt>struct foo { static constexpr size_t const N =3D
std::indexof<T>; };</tt><tt><br>
</tt><tt>// undefined behavior</tt><tt><br>
</tt><tt><br>
</tt><tt>template <typename T></tt><tt><br>
</tt><tt>constexpr size_t const bar =3D </tt><tt>std::indexof<T>;=
</tt><tt><br>
</tt><tt>// undefined behavior</tt><tt><br>
</tt><tt><br>
</tt><tt>template <typename T></tt><tt><br>
</tt><tt>using baz =3D std::indexof<T>;</tt><tt><br>
</tt><tt>// iffy but probably well-defined anywhere std::indexof
would be well-defined</tt><tt><br>
</tt><br>
Behavior of std::indexof<T, N> (with user-supplied N) is
perfectly well-defined because that would sidestep the spooky/unsafe
default value computation. It would also be perfectly useless,
unless you happened to need a mapping from types to size_t in some
other context, and were willing to set it up manually.<br>
<br>
I'm torn: namespace std is much less crowded than the global
namespace, so std::indexof is more likely to be available than a new
indexof keyword. But the __indexof() operator is much safer because
improper uses fail to compile.<br>
<br>
Thoughts?<br>
Ryan<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------050505060703020302060207--
.
Author: Edward Catmur <ed@catmur.co.uk>
Date: Mon, 27 Jul 2015 11:42:56 -0700 (PDT)
Raw View
------=_Part_738_774186642.1438022576740
Content-Type: multipart/alternative;
boundary="----=_Part_739_140083683.1438022576741"
------=_Part_739_140083683.1438022576741
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Monday, 27 July 2015 12:13:29 UTC+1, David Krauss wrote:
>
> On 2015=E2=80=9307=E2=80=9327, at 4:23 PM, Edward Catmur <e...@catmur.co.=
uk <javascript:>>=20
> wrote:
> template<std::size_t I, class T> T& tuple_get(tuple_base<I, T>& obj) {=20
> return obj.value; }
>
> We=E2=80=99re getting a bit off topic here, but you can=E2=80=99t get cla=
ss T without=20
> using recursion in the form of tuple_element.
>
Sorry for the continued derailing; I'd like to know if I'm doing anything=
=20
illegal. Can't the compiler deduce T from the tuple_base argument?
template<int I, class T> struct B { T value; };
template<int I, class T> T& get(B<I, T>& b) { return b.value; }
struct X : B<0, int>, B<1, float> {} x;
float& f =3D get<1>(x); // seems to work
You can implement get without changing __tuple_base, by using overload=20
> resolution over indexed dispatch tags, but that adds inefficiency.
>
> Naming the derived type tuple<T...> as a template argument merely=20
> mentions a preexisting specialization, which doesn=E2=80=99t require any =
extra=20
> compiler resources. Anyway, the same effect could be achieved by nesting=
=20
> tuple_base inside a class parameterized on <T...>.
>
Yes, but that makes the initial base classes of tuple<int, float> and=20
tuple<int, float, char> distinct when they could be the same type, which=20
does require extra compiler resources; and it bloats the symbol table.
> Here=E2=80=99s a working proof of concept. amalgam_ftor can be found here=
=20
> <https://code.google.com/p/c-plus/source/browse/src/util.h>.
> [...]
> The complexity here is in forming and using the overload set at the time=
=20
> tuple is instantiated. Hopefully all the bootstrap stuff (overload set,=
=20
> etc) gets garbage collected, and what=E2=80=99s left is an ideal map from=
numbers,=20
> through base classes, to types.
>
Very impressive. I get a bit uncomfortable seeing decltype in=20
metaprogramming, but maybe I'm just showing my age.
> That particular form of the trick requires N instantiations, so it looks=
=20
> less efficient than recursion. Unless you have a parallelized template=20
> engine, recursion will win by early exit.
>
O(N/2) beats O(N) only when the constants are the same, and nonrecursive=20
code can be more amenable to optimization - vectorization as well as=20
parallelization. I guess the only way to tell is profiling.
> I didn=E2=80=99t say it was surprising. In my experience, when a metaprog=
ram needs=20
> random access, an overload set is a better tool. Instantiating very large=
=20
> std::tuple objects is a red flag. std::tuple_element really shouldn=E2=80=
=99t be=20
> a bottleneck. Implementation effort is better spent optimizing the real=
=20
> fundamentals: name lookup, class template instantiation, overload=20
> resolution constexpr evaluation, etc. The true performance culprits can b=
e=20
> found by running real workloads in profiler, and there=E2=80=99s no sense=
in second=20
> guessing the work of guys who do that.
>
It's not just about the compiler, though; recursive implementations spill=
=20
details into error messages and into linker and debug symbols. Stepping=20
through a deep recursive call to std::get is annoying when it could be done=
=20
in a single frame (or 2 at most).
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_739_140083683.1438022576741
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<br>On Monday, 27 July 2015 12:13:29 UTC+1, David Krauss wrote:<blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div style=3D"word-wrap:break-word"><div>=
<blockquote type=3D"cite"><div>On 2015=E2=80=9307=E2=80=9327, at 4:23 PM, E=
dward Catmur <<a href=3D"javascript:" target=3D"_blank" rel=3D"nofollow"=
onmousedown=3D"this.href=3D'javascript:';return true;" onclick=3D"=
this.href=3D'javascript:';return true;">e...@catmur.co.uk</a>> w=
rote:</div><div><div style=3D"border:1px solid rgb(187,187,187);word-wrap:b=
reak-word;background-color:rgb(250,250,250)"><code><span style=3D"color:#00=
8">template</span><span style=3D"color:#660"><</span>std<span style=3D"c=
olor:#660">::</span>size_t I<span style=3D"color:#660">,</span> <span style=
=3D"color:#008">class</span> T<span style=3D"color:#660">></span> T<span=
style=3D"color:#660">&</span> tuple_get<span style=3D"color:#660">(</s=
pan>tuple_base<span style=3D"color:#660"><</span>I<span style=3D"color:#=
660">,</span> T<span style=3D"color:#660">>&</span> obj<span style=
=3D"color:#660">)</span> <span style=3D"color:#660">{</span> <span style=3D=
"color:#008">return</span> obj<span style=3D"color:#660">.</span>value<span=
style=3D"color:#660">;</span> <span style=3D"color:#660">}</span><br></cod=
e></div></div></blockquote><div>We=E2=80=99re getting a bit off topic here,=
but you can=E2=80=99t get <font face=3D"Courier">class T</font> without us=
ing recursion in the form of <font face=3D"Courier">tuple_element</font>.<b=
r></div></div></div></blockquote><div><br></div>Sorry for the continued der=
ailing; I'd like to know if I'm doing anything illegal. Can't t=
he compiler deduce T from the tuple_base argument?<div><br></div><div><div =
class=3D"prettyprint" style=3D"border: 1px solid rgb(187, 187, 187); word-w=
rap: break-word; background-color: rgb(250, 250, 250);"><code class=3D"pret=
typrint"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=
=3D"styled-by-prettify">template</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify"><</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> I</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">class</span><sp=
an 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"> </span><span style=3D"color: #008=
;" class=3D"styled-by-prettify">struct</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> B </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> T 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: #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 s=
tyle=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> I</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"> T</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 sty=
le=3D"color: #008;" class=3D"styled-by-prettify">get</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">B</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify"><</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">I</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: #660;" class=3D"styled-by-prettify">>&=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> b</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"> </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">return</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify"> b</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">value</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: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">struct</span><span style=3D"color:=
#000;" class=3D"styled-by-prettify"> X </span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">:</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> B</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify"><</span><span style=3D"color: #066;" class=3D"styled-by-pre=
ttify">0</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">int</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">>,</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> B</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;" class=3D"styled-by=
-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify=
">float</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 sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> x</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" cla=
ss=3D"styled-by-prettify">float</span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">&</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"> f </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">get</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify"><</span><sp=
an 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"c=
olor: #000;" class=3D"styled-by-prettify">x</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> =C2=A0</span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// seems to work</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br></span></div></code></div><div><br></div>=
<blockquote class=3D"gmail_quote" style=3D"border-left-width: 1px; border-l=
eft-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;=
"><div style=3D"word-wrap:break-word"><div><div>You can implement <font fac=
e=3D"Courier">get</font> without changing <font face=3D"Courier">__tuple_ba=
se</font>, by using overload resolution over indexed dispatch tags, but tha=
t adds inefficiency.</div><div><br></div><div>Naming the derived type <font=
face=3D"Courier">tuple<T...></font> as a template argument=C2=A0mere=
ly mentions a preexisting specialization, which doesn=E2=80=99t require any=
extra compiler resources. Anyway, the same effect could be achieved by nes=
ting <font face=3D"Courier">tuple_base</font> inside a class parameterized =
on <font face=3D"Courier"><T...></font>.</div></div></div></blockquot=
e><div>Yes, but that makes the initial base classes of tuple<int, float&=
gt; and tuple<int, float, char> distinct when they could be the same =
type, which does require extra compiler resources; and it bloats the symbol=
table.</div><blockquote class=3D"gmail_quote" style=3D"border-left-width: =
1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; paddi=
ng-left: 1ex;"><div style=3D"word-wrap:break-word"><div><div>Here=E2=80=99s=
a working proof of concept.=C2=A0<font face=3D"Courier">amalgam_ftor</font=
> can be found=C2=A0<a href=3D"https://code.google.com/p/c-plus/source/brow=
se/src/util.h" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'https://code.google.com/p/c-plus/source/browse/src/util.h';retu=
rn true;" onclick=3D"this.href=3D'https://code.google.com/p/c-plus/sour=
ce/browse/src/util.h';return true;">here</a>.<br></div><div>[...]</div>=
<div>The complexity here is in forming and using the overload set at the ti=
me <font face=3D"Courier">tuple</font> is instantiated. Hopefully all the b=
ootstrap stuff (overload set, etc) gets garbage collected, and what=E2=80=
=99s left is an ideal map from numbers, through base classes, to types.</di=
v></div></div></blockquote><div>=C2=A0Very impressive. I get a bit uncomfor=
table seeing decltype in metaprogramming, but maybe I'm just showing my=
age.</div><blockquote class=3D"gmail_quote" style=3D"border-left-width: 1p=
x; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding=
-left: 1ex;"><div style=3D"word-wrap:break-word"><div><div></div><div>That =
particular form of the trick requires N instantiations, so it looks less ef=
ficient than recursion. Unless you have a parallelized template engine, rec=
ursion will win by early exit.<br></div></div><div></div></div></blockquote=
><div>O(N/2) beats O(N) only when the constants are the same, and nonrecurs=
ive code can be more amenable to optimization - vectorization as well as pa=
rallelization. I guess the only way to tell is profiling.</div><blockquote =
class=3D"gmail_quote" style=3D"border-left-width: 1px; border-left-color: r=
gb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div style=
=3D"word-wrap:break-word"><div>I didn=E2=80=99t say it was surprising. In m=
y experience, when a metaprogram needs random access, an overload set is a =
better tool. Instantiating very large <font face=3D"Courier">std::tuple</fo=
nt>=C2=A0objects is a red flag. <font face=3D"Courier">std::tuple_element</=
font> really shouldn=E2=80=99t be a bottleneck. Implementation effort is be=
tter spent optimizing the real fundamentals: name lookup, class template in=
stantiation, overload resolution constexpr evaluation, etc. The true perfor=
mance culprits can be found by running real workloads in profiler, and ther=
e=E2=80=99s no sense in second guessing the work of guys who do that.</div>=
</div></blockquote><div>It's not just about the compiler, though; recur=
sive implementations spill details into error messages and into linker and =
debug symbols. Stepping through a deep recursive call to std::get is annoyi=
ng when it could be done in a single frame (or 2 at most).</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_739_140083683.1438022576741--
------=_Part_738_774186642.1438022576740--
.
Author: Edward Catmur <ed@catmur.co.uk>
Date: Mon, 27 Jul 2015 12:29:48 -0700 (PDT)
Raw View
------=_Part_3343_1197000723.1438025388967
Content-Type: multipart/alternative;
boundary="----=_Part_3344_1919244002.1438025388967"
------=_Part_3344_1919244002.1438025388967
Content-Type: text/plain; charset=UTF-8
On Monday, 27 July 2015 19:00:56 UTC+1, Ryan Johnson wrote:
>
> You actually make a very good point that N3728 only addresses types, not
> integer sequences, and so is orthogonal in that respect.
>
Hey! N3728 mentions non-type parameters (in the context of reflection, but
still) and in any case even if restricted to type parameters one could use
a sequence of integral_constant as a stand-in for an integer sequence (at
some cost of efficiency, perhaps).
> I also suspect strongly that N3728 will not mature in time for C++17, so
> let's drop it from the discussion and focus on stand-alone solutions to the
> problem at hand.
>
Agreed; I'll shut up now.
> I'm torn: namespace std is much less crowded than the global namespace, so
> std::indexof is more likely to be available than a new indexof keyword. But
> the __indexof() operator is much safer because improper uses fail to
> compile.
>
In order to avoid adding a new keyword, is there any potential to stack a
.... token on top of an existing keyword or operator, as was done with
sizeof...? It'd have to avoid colliding with fold-expression, of course.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3344_1919244002.1438025388967
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, 27 July 2015 19:00:56 UTC+1, Ryan Johnson wrot=
e:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;">
=20
=20
=20
<div bgcolor=3D"#FFFFFF" text=3D"#000000">
<div>You actually make a very good point that N3728 only addresses type=
s,
not integer sequences, and so is orthogonal in that respect.</div></div=
></blockquote><div><br></div><div><div>Hey! N3728 mentions non-type paramet=
ers (in the context of reflection, but still) and in any case even if restr=
icted to type parameters one could use a sequence of integral_constant as a=
stand-in for an integer sequence (at some cost of efficiency, perhaps).</d=
iv></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin=
: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div=
bgcolor=3D"#FFFFFF" text=3D"#000000"><div> I also
suspect strongly that N3728 will not mature in time for C++17, so
let's drop it from the discussion and focus on stand-alone solution=
s
to the problem at hand.=C2=A0<br></div></div></blockquote><div><br></di=
v><div>Agreed; I'll shut up now.</div><div>=C2=A0<br></div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div bgcolor=3D"#FFFFFF" text=3D"#000000">=
<div></div>
I'm torn: namespace std is much less crowded than the global
namespace, so std::indexof is more likely to be available than a new
indexof keyword. But the __indexof() operator is much safer because
improper uses fail to compile.<br></div></blockquote><div><br></div><di=
v>In order to avoid adding a new keyword, is there any potential to stack a=
... token on top of an existing keyword or operator, as was done with size=
of...? It'd have to avoid colliding with fold-expression, of course.</d=
iv></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3344_1919244002.1438025388967--
------=_Part_3343_1197000723.1438025388967--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Mon, 27 Jul 2015 14:07:12 -0600
Raw View
This is a multi-part message in MIME format.
--------------010505080600030801050001
Content-Type: text/plain; charset=UTF-8; format=flowed
On 27/07/2015 1:29 PM, Edward Catmur wrote:
> On Monday, 27 July 2015 19:00:56 UTC+1, Ryan Johnson wrote:
>
> I'm torn: namespace std is much less crowded than the global
> namespace, so std::indexof is more likely to be available than a
> new indexof keyword. But the __indexof() operator is much safer
> because improper uses fail to compile.
>
>
> In order to avoid adding a new keyword, is there any potential to
> stack a ... token on top of an existing keyword or operator, as was
> done with sizeof...? It'd have to avoid colliding with
> fold-expression, of course.
Actually, that's a good point: indexof...(T) would probably parse
unambiguously while still allowing `indexof' to be a normal identifier.
As a bonus, it would be obvious at a glance that the operator is related
to parameter packs, which is not true of the __indexof() I originally
proposed:
template <typename... Ts>
int hash(std::tuple<Ts...> const &tup)
{
using std::hash; // ADL
return (... ^ hash(tup.get<indexof...(Ts)>(tup)));
}
template <typename... Ts>
auto reverse(std::tuple<Ts...> const &tup)
{
using rtuple = std::tuple<
std::tuple<Ts...>,
typename std::tuple_element_t<sizeof...(Ts) - indexof...(Ts) - 1>>;
return rtuple{std::get<sizeof...(Ts) - indexof...(Ts) - 1>(tup)...};
}
There's a bit of a mismatch with sizeof...(T) because the latter is a
simple scalar expression that happens to take an unexpanded parameter
pack as an argument, while the former expands with its parameter pack.
But maybe that doesn't matter too much?
Ryan
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--------------010505080600030801050001
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 27/07/2015 1:29 PM, Edward Catmur
wrote:<br>
</div>
<blockquote
cite=3D"mid:56e31a0f-21aa-4940-85dc-dd2cc2a51ab7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">On Monday, 27 July 2015 19:00:56 UTC+1, Ryan
Johnson wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000"> I'm torn: namespace st=
d
is much less crowded than the global namespace, so
std::indexof is more likely to be available than a new
indexof keyword. But the __indexof() operator is much safer
because improper uses fail to compile.<br>
</div>
</blockquote>
<div><br>
</div>
<div>In order to avoid adding a new keyword, is there any
potential to stack a ... token on top of an existing keyword
or operator, as was done with sizeof...? It'd have to avoid
colliding with fold-expression, of course.</div>
</div>
</blockquote>
Actually, that's a good point: indexof...(T) would probably parse
unambiguously while still allowing `indexof' to be a normal
identifier. As a bonus, it would be obvious at a glance that the
operator is related to parameter packs, which is not true of the
__indexof() I originally proposed:<br>
<br>
template <typename... Ts><br>
int hash(std::tuple<Ts...> const &tup)<br>
{<br>
=C2=A0=C2=A0 using std::hash; // ADL<br>
=C2=A0=C2=A0 return (... ^ hash(tup.get<indexof...(Ts)>(tup)));<b=
r>
}<br>
<br>
template <typename... Ts><br>
auto reverse(std::tuple<Ts...> const &tup)<br>
{<br>
=C2=A0=C2=A0 using rtuple =3D std::tuple<<br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 std::tuple<Ts...>, <br>
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 typename std::tuple_element_t<sizeof.=
...(Ts) -
indexof...(Ts) - 1>>;<br>
=C2=A0=C2=A0 return rtuple{std::get<sizeof...(Ts) - indexof...(Ts) -
1>(tup)...};<br>
}<br>
<br>
There's a bit of a mismatch with sizeof...(T) because the latter is
a simple scalar expression that happens to take an unexpanded
parameter pack as an argument, while the former expands with its
parameter pack.=C2=A0 But maybe that doesn't matter too much?<br>
<br>
Ryan<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------010505080600030801050001--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Mon, 27 Jul 2015 14:07:23 -0600
Raw View
This is a multi-part message in MIME format.
--------------070307030804050204080705
Content-Type: text/plain; charset=UTF-8; format=flowed
On 27/07/2015 1:29 PM, Edward Catmur wrote:
> On Monday, 27 July 2015 19:00:56 UTC+1, Ryan Johnson wrote:
>
> I'm torn: namespace std is much less crowded than the global
> namespace, so std::indexof is more likely to be available than a
> new indexof keyword. But the __indexof() operator is much safer
> because improper uses fail to compile.
>
>
> In order to avoid adding a new keyword, is there any potential to
> stack a ... token on top of an existing keyword or operator, as was
> done with sizeof...? It'd have to avoid colliding with
> fold-expression, of course.
Actually, that's a good point: indexof...(T) would probably parse
unambiguously while still allowing `indexof' to be a normal identifier.
As a bonus, it would be obvious at a glance that the operator is related
to parameter packs, which is not true of the __indexof() I originally
proposed:
template <typename... Ts>
int hash(std::tuple<Ts...> const &tup)
{
using std::hash; // ADL
return (... ^ hash(tup.get<indexof...(Ts)>(tup)));
}
template <typename... Ts>
auto reverse(std::tuple<Ts...> const &tup)
{
using rtuple = std::tuple<
std::tuple<Ts...>,
typename std::tuple_element_t<sizeof...(Ts) - indexof...(Ts) - 1>>;
return rtuple{std::get<sizeof...(Ts) - indexof...(Ts) - 1>(tup)...};
}
There's a bit of a mismatch with sizeof...(T) because the latter is a
simple scalar expression that happens to take an unexpanded parameter
pack as an argument, while the former expands with its parameter pack.
But maybe that doesn't matter too much?
Ryan
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--------------070307030804050204080705
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 27/07/2015 1:29 PM, Edward Catmur
wrote:<br>
</div>
<blockquote
cite=3D"mid:56e31a0f-21aa-4940-85dc-dd2cc2a51ab7@isocpp.org"
type=3D"cite">
<div dir=3D"ltr">On Monday, 27 July 2015 19:00:56 UTC+1, Ryan
Johnson wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div bgcolor=3D"#FFFFFF" text=3D"#000000"> I'm torn: namespace st=
d
is much less crowded than the global namespace, so
std::indexof is more likely to be available than a new
indexof keyword. But the __indexof() operator is much safer
because improper uses fail to compile.<br>
</div>
</blockquote>
<div><br>
</div>
<div>In order to avoid adding a new keyword, is there any
potential to stack a ... token on top of an existing keyword
or operator, as was done with sizeof...? It'd have to avoid
colliding with fold-expression, of course.</div>
</div>
</blockquote>
Actually, that's a good point: indexof...(T) would probably parse
unambiguously while still allowing `indexof' to be a normal
identifier. As a bonus, it would be obvious at a glance that the
operator is related to parameter packs, which is not true of the
__indexof() I originally proposed:<br>
<br>
<tt>template <typename... Ts></tt><tt><br>
</tt><tt>int hash(std::tuple<Ts...> const &tup)</tt><tt><br>
</tt><tt>{</tt><tt><br>
</tt><tt>=C2=A0=C2=A0 using std::hash; // ADL</tt><tt><br>
</tt><tt>=C2=A0=C2=A0 return (... ^ hash(tup.get<indexof...(Ts)>(=
tup)));</tt><tt><br>
</tt><tt>}</tt><tt><br>
</tt><tt><br>
</tt><tt>template <typename... Ts></tt><tt><br>
</tt><tt>auto reverse(std::tuple<Ts...> const &tup)</tt><tt><=
br>
</tt><tt>{</tt><tt><br>
</tt><tt>=C2=A0=C2=A0 using rtuple =3D std::tuple<</tt><tt><br>
</tt><tt>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 </tt><tt>std::tuple<Ts...>=
;, </tt><tt><br>
</tt><tt>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 </tt><tt>typename
std::tuple_element_t<sizeof...(Ts) - indexof...(Ts) -
1>>;</tt><tt><br>
</tt><tt>=C2=A0=C2=A0 return rtuple{std::get<sizeof...(Ts) - indexof=
....(Ts)
- 1>(tup)...};</tt><tt><br>
</tt><tt>}</tt><tt><br>
</tt><br>
There's a bit of a mismatch with sizeof...(T) because the latter is
a simple scalar expression that happens to take an unexpanded
parameter pack as an argument, while the former expands with its
parameter pack.=C2=A0 But maybe that doesn't matter too much?<br>
<br>
Ryan<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------070307030804050204080705--
.
Author: Ryan Johnson <scovich@gmail.com>
Date: Mon, 27 Jul 2015 14:18:26 -0600
Raw View
This is a multi-part message in MIME format.
--------------080607010804090708020202
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
On 27/07/2015 12:42 PM, Edward Catmur wrote:
>
> On Monday, 27 July 2015 12:13:29 UTC+1, David Krauss wrote:
>
>> On 2015=E2=80=9307=E2=80=9327, at 4:23 PM, Edward Catmur <e...@catmu=
r.co.uk
>> <javascript:>> wrote:
>> |template<std::size_t I, class T> T& tuple_get(tuple_base<I, T>&
>> obj) { return obj.value; }
>> |
> We=E2=80=99re getting a bit off topic here, but you can=E2=80=99t get=
class T
> without using recursion in the form of tuple_element.
>
>
> Sorry for the continued derailing; I'd like to know if I'm doing=20
> anything illegal. Can't the compiler deduce T from the tuple_base=20
> argument?
From what I understood, he agreed it would work, but thought it would=20
require more overload resolution effort from the compiler at the call=20
site than his mapping trick did:
>> You can implement get without changing __tuple_base, by using=20
>> overload resolution over indexed dispatch tags, but that adds=20
>> inefficiency.
> O(N/2) beats O(N) only when the constants are the same, and=20
> nonrecursive code can be more amenable to optimization - vectorization=20
> as well as parallelization. I guess the only way to tell is profiling.
But on the other hand these compilers have been optimizing the recursive=20
case for years and only recently started worrying about parameter packs,=20
so there could be a performance differential there (albeit a temporary=20
one, hopefully).
> I didn=E2=80=99t say it was surprising. In my experience, when a
> metaprogram needs random access, an overload set is a better tool.
> Instantiating very large std::tuple objects is a red flag.
> std::tuple_element really shouldn=E2=80=99t be a bottleneck.
> Implementation effort is better spent optimizing the real
> fundamentals: name lookup, class template instantiation, overload
> resolution constexpr evaluation, etc. The true performance
> culprits can be found by running real workloads in profiler, and
> there=E2=80=99s no sense in second guessing the work of guys who do t=
hat.
>
> It's not just about the compiler, though; recursive implementations=20
> spill details into error messages and into linker and debug symbols.=20
> Stepping through a deep recursive call to std::get is annoying when it=20
> could be done in a single frame (or 2 at most).
Agree. Anything that allows the compiler to vomit simpler/fewer lines of=20
template names is a Good Thing.
Ryan
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--------------080607010804090708020202
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta content=3D"text/html; charset=3Dutf-8" http-equiv=3D"Content-Type=
">
</head>
<body bgcolor=3D"#FFFFFF" text=3D"#000000">
<div class=3D"moz-cite-prefix">On 27/07/2015 12:42 PM, Edward Catmur
wrote:<br>
</div>
<blockquote
cite=3D"mid:f71a2972-b2db-4ef6-9ac3-a7dcd1c1ea63@isocpp.org"
type=3D"cite"><br>
On Monday, 27 July 2015 12:13:29 UTC+1, David Krauss wrote:
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<div style=3D"word-wrap:break-word">
<div>
<blockquote type=3D"cite">
<div>On 2015=E2=80=9307=E2=80=9327, at 4:23 PM, Edward Catmur=
<<a
moz-do-not-send=3D"true" href=3D"javascript:"
target=3D"_blank" rel=3D"nofollow"
onmousedown=3D"this.href=3D'javascript:';return true;"
onclick=3D"this.href=3D'javascript:';return true;">e...@c=
atmur.co.uk</a>>
wrote:</div>
<div>
<div style=3D"border:1px solid
rgb(187,187,187);word-wrap:break-word;background-color:rg=
b(250,250,250)"><code><span
style=3D"color:#008">template</span><span
style=3D"color:#660"><</span>std<span
style=3D"color:#660">::</span>size_t I<span
style=3D"color:#660">,</span> <span
style=3D"color:#008">class</span> T<span
style=3D"color:#660">></span> T<span
style=3D"color:#660">&</span> tuple_get<span
style=3D"color:#660">(</span>tuple_base<span
style=3D"color:#660"><</span>I<span
style=3D"color:#660">,</span> T<span
style=3D"color:#660">>&</span> obj<span
style=3D"color:#660">)</span> <span
style=3D"color:#660">{</span> <span
style=3D"color:#008">return</span> obj<span
style=3D"color:#660">.</span>value<span
style=3D"color:#660">;</span> <span
style=3D"color:#660">}</span><br>
</code></div>
</div>
</blockquote>
<div>We=E2=80=99re getting a bit off topic here, but you can=E2=
=80=99t get <font
face=3D"Courier">class T</font> without using recursion in
the form of <font face=3D"Courier">tuple_element</font>.<br>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
Sorry for the continued derailing; I'd like to know if I'm doing
anything illegal. Can't the compiler deduce T from the tuple_base
argument?</blockquote>
From what I understood, he agreed it would work, but thought it
would require more overload resolution effort from the compiler at
the call site than his mapping trick did:<br>
<blockquote type=3D"cite">
<blockquote type=3D"cite">You can implement <font face=3D"Courier">ge=
t</font>
without changing <font face=3D"Courier">__tuple_base</font>, by
using overload resolution over indexed dispatch tags, but that
adds inefficiency.</blockquote>
</blockquote>
<br>
<br>
<blockquote
cite=3D"mid:f71a2972-b2db-4ef6-9ac3-a7dcd1c1ea63@isocpp.org"
type=3D"cite">
<div>O(N/2) beats O(N) only when the constants are the same, and
nonrecursive code can be more amenable to optimization -
vectorization as well as parallelization. I guess the only way
to tell is profiling.</div>
</blockquote>
But on the other hand these compilers have been optimizing the
recursive case for years and only recently started worrying about
parameter packs, so there could be a performance differential there
(albeit a temporary one, hopefully).<br>
<br>
<blockquote
cite=3D"mid:f71a2972-b2db-4ef6-9ac3-a7dcd1c1ea63@isocpp.org"
type=3D"cite">
<div>
<blockquote class=3D"gmail_quote" style=3D"border-left-width: 1px;
border-left-color: rgb(204, 204, 204); border-left-style:
solid; padding-left: 1ex;">
<div style=3D"word-wrap:break-word">
<div>I didn=E2=80=99t say it was surprising. In my experience, =
when
a metaprogram needs random access, an overload set is a
better tool. Instantiating very large <font
face=3D"Courier">std::tuple</font>=C2=A0objects is a red fl=
ag.
<font face=3D"Courier">std::tuple_element</font> really
shouldn=E2=80=99t be a bottleneck. Implementation effort is b=
etter
spent optimizing the real fundamentals: name lookup, class
template instantiation, overload resolution constexpr
evaluation, etc. The true performance culprits can be
found by running real workloads in profiler, and there=E2=80=
=99s
no sense in second guessing the work of guys who do that.</di=
v>
</div>
</blockquote>
<div>It's not just about the compiler, though; recursive
implementations spill details into error messages and into
linker and debug symbols. Stepping through a deep recursive
call to std::get is annoying when it could be done in a single
frame (or 2 at most).</div>
</div>
</blockquote>
Agree. Anything that allows the compiler to vomit simpler/fewer
lines of template names is a Good Thing.<br>
<br>
Ryan<br>
<br>
</body>
</html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--------------080607010804090708020202--
.