Date: Thu, 19 Nov 2020 11:40:28 +0100
Speaking of unpacking meta::info ranges, I personally see operator |something|... as different type of operator |something| which is to me same thing as having multiple operators per AST type.
So if I know the something is a pack/range, it should reify into a pack/range. In the example we can go with library solution:
enum E { A, B, C};
constexpr auto enums = meta::enumerators_of(reflexpr(E));
int vals[] {|meta::pack_from_range(enums)|...};
And here the ... is unpacking an ordinary pack created by the reify operator.
Hana
> On 19. 11. 2020, at 2:55, Barry Revzin via SG7 <sg7_at_[hidden]> wrote:
>
> 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
> --
> SG7 mailing list
> SG7_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/sg7
So if I know the something is a pack/range, it should reify into a pack/range. In the example we can go with library solution:
enum E { A, B, C};
constexpr auto enums = meta::enumerators_of(reflexpr(E));
int vals[] {|meta::pack_from_range(enums)|...};
And here the ... is unpacking an ordinary pack created by the reify operator.
Hana
> On 19. 11. 2020, at 2:55, Barry Revzin via SG7 <sg7_at_[hidden]> wrote:
>
> 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
> --
> SG7 mailing list
> SG7_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/sg7
Received on 2020-11-19 04:40:35