Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to reflect template parameter pack? #276

Open
rbock opened this issue Nov 23, 2020 · 11 comments
Open

How to reflect template parameter pack? #276

rbock opened this issue Nov 23, 2020 · 11 comments
Labels

Comments

@rbock
Copy link

rbock commented Nov 23, 2020

Hi,

I probably searched for the wrong terms, but I could not find a way to reflect a parameter pack? I want to consteval-iterate over the template parameters of a class template. Here is one of the (incorrect) things I tried:

#include <experimental/meta>
#include <experimental/compiler>

namespace meta = std::experimental::meta;

template<typename... NamedExpressions>
class select_clause
{
    consteval {
        auto pack_info = reflexpr(NamedExpressions); // I assume that this is wrong?

        for (const meta::info expression_info : meta::template_param_range(pack_info)) {
            -> fragment struct {
                int i;
            };
        }
    }

};

auto x = select_clause<int>{};
auto y = x.i; // no member named 'i'

int main(){}

See also https://cppx.godbolt.org/z/TYT9WG

Thanks,

Roland

@TimPhoeniX
Copy link

It's not yet supported, but for now, my preferred workaround looks like this:

template<typename T>
consteval meta::info refl()
{
    return reflexpr(T);
}

template<typename... Types>
class foo
{
    consteval{
        meta::info t[sizeof...(Types)]{refl<Types>()...};
    }
};

See https://cppx.godbolt.org/z/b6Mn8z

@rbock
Copy link
Author

rbock commented Nov 23, 2020

Thanks! Quite elegant!

@rbock
Copy link
Author

rbock commented Jan 2, 2021

Do you also have a workaround for reflecting a function parameter pack?
I tried a couple of things, all of which failed. Here are a few:

template <typename T>
consteval meta::info refl(T&& t) {
  return reflexpr(t);
}

template <typename... Types>
auto foo(Types... ts){
    consteval {
        auto pack1 = reflexpr(ts); // error: reference to local variable 'ts' declared in enclosing function
        meta::info pack2[sizeof...(ts)]{reflexpr(ts)...}; // error: pack expansion does not contain any unexpanded parameter packs
        meta::info pack3[sizeof...(ts)]{refl(ts)...}; // error: reference to local variable 'ts' declared in enclosing function
    };
}

I am particularly confused by the reference to local variable error, as this seems to work totally fine in non-variadic contexts:

auto f1(int i) {
  consteval {
    auto info1 = reflexpr(i); // OK
    auto info2 = refl(i);     // OK
  };
}

See https://cppx.godbolt.org/z/eev8PE

@TimPhoeniX
Copy link

See https://cppx.godbolt.org/z/WMsqfh.

Weirdly, the block evaluates and you can even iterate over the array - I guess error is a bug.
However, even if it worked right, wrapping reflexpr operator in a template function will not work for function arguments - reflection will refer to wrapping function parameter and will cause segfault at runtime.
It seems that actual support for reflecting parameter pack will be needed for this one.

@DarkArc
Copy link
Contributor

DarkArc commented Jan 4, 2021

There are a few parts to this. I've fixed reflexpr appearing in a pack expansion in the new syntax branch. i.e. things like the following should be possible:

meta::info pack_expanded [] = { reflexpr(Ts)... };

This new syntax branch in general, greatly improves our support for packs; including the introduction of a splice that forms a pack from an expandable expression i.e. ...[< pack_expanded >] would reform Ts.

As for reflexpr(Ts), support for directly reflecting packs is still being discussed, but, there should be more on all of this soon :)

@rbock
Copy link
Author

rbock commented Jan 5, 2021

The new syntax being closer to http://open-std.org/JTC1/SC22/WG21/docs/papers/2020/p2237r0.pdf ?

Would you be interested in early feedback?

@DarkArc
Copy link
Contributor

DarkArc commented Jan 5, 2021

Yes, closer to though not quite. The main difference being the use of [<, >] instead of |, | and [#, #] instead of |#, #|.

As for early feedback, sure :)

@rbock
Copy link
Author

rbock commented Jan 5, 2021

Cool, I'll switch to experimenting with that then :)

@DarkArc
Copy link
Contributor

DarkArc commented Jan 5, 2021

Fair warning: It's not yet updated for metaprogramming purposes, just the base reflection branch for the moment. Commits are also pretty volatile there (expect force pushes and history rewrites on that branch) :)

@rbock
Copy link
Author

rbock commented Jan 5, 2021

Thanks for the warning :-)

Are you planning to add metaprogramming to the same branch?

@DarkArc
Copy link
Contributor

DarkArc commented Jan 5, 2021

When we're ready I anticipate the branch will be merged into feature/reflect and then feature/metaprogramming; there might be a temporary branch say... feature/new-splice-syntax-meta? In general I'd expect everything to be in feature/reflect and feature/metaprogramming when ready.

Might be some delay in things going to compiler-explorer; we'll have to work with Matt a bit to minimize breakages of existing godbolt links -- I believe those mechanisms are already in place for other compilers he hosts though, so this shouldn't be a big deal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants