Date: Wed, 18 Nov 2020 19:55:02 -0600
Hey all,
Andrew's Metaprogramming paper allows for the following syntax (pg 19 from
D2237R1):
enum E { A, B, C};
constexpr auto enums = meta::enumerators_of(reflexpr(E));
int vals[] {|enums|... };
That is, you can directly expand a splice of enums, because it's a
constexpr range. But this is the same exact syntax that would happen if we
had a parameter pack:
template <meta::info... enums>
void f() {
int vals[] { |enums| ... };
}
And I'm concerned about implicitly treating both ranges and packs the same.
I think this could run into similar issues as we saw with expansion
statements, and similar issues to the case I talk about in P1858 (the
context here was directly expanding a tuple into its underlying parts,
which is similar to expanding a range of meta::infos into its infos):
template <typename T, typename... U>void call_f(T t, U... us){ //
Is this intended to add 't' to each element in 'us' // or is
intended to pairwise sum the tuple 't' and // the pack 'us'?
f((t + us)...);}
Here, it's easy for me to come up with examples of wanting either choice:
* call_f(tuple(1, 2), 3, 4) could be intended to call f(4, 6), doing the
pairwise sum.
* call_f(point{1, 2}, point{0, 1}, point{3, 7}) could be intended to call
f(point{1,3}, point{4,9}), adding 't' to each element.
A similar thing could come up here - where we have a range of meta::info
and a pack and may want to expand the range and may not want to:
template <typename E, typename... Args>
void foo(Args... args) {
constexpr auto enums = meta::enumerators_of(reflexpr(E));
g(|impl(enums, args)|...);
}
enum E { A, B, C };
void bar() {
foo<E>(1, 2, 3);
}
Are we calling impl(enums, 1) or are we calling impl(reflexpr(E::A), 1)?
Barry
Andrew's Metaprogramming paper allows for the following syntax (pg 19 from
D2237R1):
enum E { A, B, C};
constexpr auto enums = meta::enumerators_of(reflexpr(E));
int vals[] {|enums|... };
That is, you can directly expand a splice of enums, because it's a
constexpr range. But this is the same exact syntax that would happen if we
had a parameter pack:
template <meta::info... enums>
void f() {
int vals[] { |enums| ... };
}
And I'm concerned about implicitly treating both ranges and packs the same.
I think this could run into similar issues as we saw with expansion
statements, and similar issues to the case I talk about in P1858 (the
context here was directly expanding a tuple into its underlying parts,
which is similar to expanding a range of meta::infos into its infos):
template <typename T, typename... U>void call_f(T t, U... us){ //
Is this intended to add 't' to each element in 'us' // or is
intended to pairwise sum the tuple 't' and // the pack 'us'?
f((t + us)...);}
Here, it's easy for me to come up with examples of wanting either choice:
* call_f(tuple(1, 2), 3, 4) could be intended to call f(4, 6), doing the
pairwise sum.
* call_f(point{1, 2}, point{0, 1}, point{3, 7}) could be intended to call
f(point{1,3}, point{4,9}), adding 't' to each element.
A similar thing could come up here - where we have a range of meta::info
and a pack and may want to expand the range and may not want to:
template <typename E, typename... Args>
void foo(Args... args) {
constexpr auto enums = meta::enumerators_of(reflexpr(E));
g(|impl(enums, args)|...);
}
enum E { A, B, C };
void bar() {
foo<E>(1, 2, 3);
}
Are we calling impl(enums, 1) or are we calling impl(reflexpr(E::A), 1)?
Barry
Received on 2020-11-18 19:55:19