How to tell if a normal template is passed a parameter pack?

Hi all,

Short version:

I have implemented a new operator similar to sizeof() or alignof()---call it foo()---and have the following code:

template <typename... Ts>
struct A {
    static constexpr size_t const values = {foo(Ts)...};

template <typename T, size_t N=foo(T)>
constexpr size_t const foo_value= N;

template <typename... Ts>
struct B {
    static constexpr size_t const values = {foo_value<Ts>...};

It so happens that clang::FooExpr--which represents foo() internally---changes its behavior depending on whether it was passed a scalar parameter (e.g. foo_value) or a parameter pack (e.g. struct A). Context for that given below.

THE QUESTION: is there a way FooExpr can detect that foo() is indirectly dealing with a parameter pack when struct B passes a parameter pack to foo_value?

(please CC me in replies)

(details and context below for the interested reader)

Ryan Johnson

What I've tried so far:

It's easy enough to detect from Parser::ParseUnaryExprOrTypeTraitExpression() that struct A directly passes an unexpanded parameter pack to foo(), and it's equally easy to detect that foo_value directly passes a scalar parameter to foo().

Detecting the indirect parameter pack obviously can't be done when foo_value is parsed, though, and I can't figure out how to make it notice later that the initial scalar parameter passed by the foo_value template is actually an unexpanded parameter pack when struct B uses it.

I suspect TreeTranstform<Derived>::TransformFooExpr(FooExpr *E) would be the correct place for this sort of analysis, but all the macro-powered code that drives TreeTransform is making it hard for me to tell how I might go about that (or whether it's even possible). Having failed to find an answer source diving, I was hoping somebody could give some pointers of where to look and/or how to approach this problem?

Longer version, with context and motivation:

I have successfully implemented a new built-in function, __indexof(), which is similar to sizeof...() in that it takes an argument pack and returns a size_t. However, __indexof() is magical in that it returns a different value for each member of the pack during expansion---namely that member's position in the expansion:

template <typename... Ts>
struct indexes {
    static constexpr const size_t values = {__indexof(Ts)...};
    // ^^^ values = {0, 1, 2, ...}

I'm hoping to propose this as a new C++17 feature [1], and it would be very nice if it were possible to wrap the magic __indexof() operator in a variable template like this:

template <typename T, size_t N=__indexof(T)>
constexpr size_t const indexof = N;

... to hide the scary/magical __indexof(T) behind a normal-looking template facade.

Unfortunately, I'm having trouble figuring out how to go about this, because the indexof template variable thinks it is dealing with a scalar parameter, not a parameter pack. I implemented __indexof() by studying the implementations of sizeof...() and C++17 fold expressions, but neither of them applies in this case and my attempts at source diving have not turned up an answer.

[1] Redirecting to Google Groups