Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
377 views
in Technique[技术] by (71.8m points)

c++ - Can I expand a parameters pack and define an arguments list with it?

From [temp.variadic] (working draft) it seemed to me that a parameters pack can be expanded while defining an arguments list of another template class or function.

Consider the following class:

template<typename... T>
struct S {
    template<T... I>
    void m() {}
};

int main() {
    S<int, char> s;
    // ...
}

The intent is to capture the types used to specialize the template class S and use them to define an arguments list of non-type parameters for the member method m (T is limited to a few types, of course, but this isn't the argument of the question).

Is this legal code? Can I use a parameter pack the way I used it or am I misinterpreting the standard (pretty sure that's the case indeed)?


In order to add more details to the question, here are some results from a few experiments with the major compilers:

At least, compilers seem to be as confused as me.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The definition of the template S, and the instantiation of S<int, char>, are valid.

See [temp.param]/15: "A template parameter pack that is a parameter-declaration whose type contains one or more unexpanded parameter packs is a pack expansion."

This means that template<T ...I> can mean one of two different things: if T is a non-pack type, then it declares a normal parameter pack, accepting any number of Ts. However, if T contains an unexpanded parameter pack, then the parameter declaration is instead expanded into a sequence of parameters when the outer template is instantiated.

Your first call to m is valid, but your second and third calls to m are ill-formed

The instantiation of S<int, char> looks like this:

template<>
struct S<int, char> {
  template<int I$0, char I$1>
  void m() {}
};

(where I$0 and I$1 are the first and second slices of the pack I).

Therefore (because neither I$0 nor I$1 can be deduced from a call to m), s.m<0,'c'>() is valid but s.m<0>() and s.m<>() are ill-formed.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...