def foo(first_argument, *other_arguments_as_tuple):
print("the first argument is", first_argument)
print("the remaining arguments in tuple form are", other_arguments_as_tuple)
print("the remaining arguments in unpacked form are", *other_arguments_as_tuple)
template<class ...Args>
void foo(Args... args){
// Args is an ordinary type of the form std::tuple<...some deduced types...>
// args is an instance of Args
bar(args...); // ... is a special operator of std::tuple.
// As args is just a tuple we can do the following with ease
har(std::get<5>(args), std::get<3>(args), std::get<2>(args));
}
Because a template argument pack is not a real type; it is a concept
that exists only prior to code generation, at which time it is expanded
inline. If you try to make them a tuple, you are forcing an object to be
constructed from the arguments, where currently we don't do that.
template<class ... Args> // the ... would become superfluous here
void foo(Args...args); // Args is inferred as std::tuple type, args as instance of this type
template<class ... Args> // the ... would become superfluous here
class Foo; // Args is inferred as std::tuple type, there is no instance
std::tuple<int, std::string>a;
foo(a...); // compiler replaces this with foo(get<0>(a), get<1>(a));
foo(bar(a)...); // compiler replaces this with foo(bar(get<0>(a)), bar(get<1>(a)));
typedef std::tuple<int, std::string> K;
std::pair<K...> x; // compiler replaces this with std::pair<int, std::string>
@Johannes: Indeed, initializer_lists are a third form of tuples.
Matthew Woehlke wrote:Because a template argument pack is not a real type; it is a concept
that exists only prior to code generation, at which time it is expanded
inline. If you try to make them a tuple, you are forcing an object to be
constructed from the arguments, where currently we don't do that.
I do not see why unpacking tuple types/argument packs before code generation is something useful. I understand that this is the way things happen to be. What I do not see is the advantage of having this. What I however do see are the advantages of having just one tuple in the language: Less gluing code needed, IMO simpler semantics, and stuff like unpacking arbitrary tuples just works.
What is the reason that you want to have unpackable types beyond tuples and the semi-type-like argument packs?
Can someone come up with code that is legal today but that would break or misbehave if one did the changed proposed in my first email?
@Johannes: Indeed, initializer_lists are a third form of tuples.
Matthew Woehlke wrote:Because a template argument pack is not a real type; it is a concept
that exists only prior to code generation, at which time it is expanded
inline. If you try to make them a tuple, you are forcing an object to be
constructed from the arguments, where currently we don't do that.
I do not see why unpacking tuple types/argument packs before code generation is something useful. I understand that this is the way things happen to be. What I do not see is the advantage of having this. What I however do see are the advantages of having just one tuple in the language: Less gluing code needed, IMO simpler semantics, and stuff like unpacking arbitrary tuples just works.
What is the reason that you want to have unpackable types beyond tuples and the semi-type-like argument packs?
Can someone come up with code that is legal today but that would break or misbehave if one did the changed proposed in my first email?
The summary of the changes would be:
template<class ... Args> // the ... would become superfluous here
void foo(Args...args); // Args is inferred as std::tuple type, args as instance of this type
template<class ... Args> // the ... would become superfluous here
class Foo; // Args is inferred as std::tuple type, there is no instance
std::tuple<int, std::string>a;
foo(a...); // compiler replaces this with foo(get<0>(a), get<1>(a));
foo(bar(a)...); // compiler replaces this with foo(bar(get<0>(a)), bar(get<1>(a)));
typedef std::tuple<int, std::string> K;
std::pair<K...> x; // compiler replaces this with std::pair<int, std::string>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.
What it most certainly would do is turn fast, compiler-generated code into slower, library-based code.
On Friday, October 16, 2015 at 5:10:30 PM UTC-4, Matthew Woehlke wrote:On 2015-10-16 16:52, Vicente J. Botet Escriba wrote:Le 12/10/15 16:37, Matthew Woehlke a écrit :Note that there is a problem with std::x::apply; it does not provide an equivalent for this Python code: t = make_some_tuple foo(arg1, arg2, *t, argn)You could have invoke(foo, arg1, arg2, args(t), argn); where args(t) wraps a tuple as ref wraps a reference so that invoke(foo, arg1, arg2, args(t), argn); would unpack the wrapped tuple t and be equivalent to invoke(foo, arg1, arg2, get<0>(t), ..., get<k-1>(t), argn); // k is the tuple_size of tI'm confused; how would you implement this 'args' *in current C++*? (By "current", I'll give you c++1z in its form as of today.) -- MatthewOne way (perfect forwarding omitted for brevity): `args()` return a special type (e.g. "tuple_wrapper").
Write a fixup_args() that wraps ordinary arguments into a (single-element) std::tuple with forward_as_tuple, and unwraps tuple_wrapper into a tuple. Then `apply(foo, tuple_cat(fixup_args(arguments)...));`