πŸ“œ ⬆️ ⬇️

Ignore extra function arguments in C ++.

Hi, Habr.

Once, on a beautiful Sunday afternoon, I wrote the code for one of my projects . The code looked something like this, to simplify:
const bool exists = WithObject (objectId, [] (const Media::IAudioSource*, const QModelIndex&) { return true; }, [] (const QModelIndex&) { return false; }); 

WithObject tries to find some object by its ID and executes the first functor if it is found, otherwise it executes the second functor if the object is not found. In this case, the value returned by the completed functor is returned (it is assumed that the return type of the second functor is reducible to the type of the first). At the same time, any different useful information obtained during the search (for example, the object itself) is transferred to the functors.

The above code, respectively, simply checks for the existence of an object, and the arguments that WithObject passes to the functors are not needed. So, I thought, it would be nice to write such a function DropArgs() , so that this code
 const bool exists = WithObject (objectId, DropArgs ([] { return true; }), DropArgs ([] { return false; })); 
was correct. Or, which is the same, so that you can write DropArgs ([] { return false; }) (0, 3.14, "foobar"); .
And if only the first N arguments are needed, the rest could also be omitted: DropArgs ([] (int n) { return n; }) (0, 3.14, "foobar"); .
')
We will think in C ++ 14, if possible trying to maintain compatibility with C ++ 11. In fact, from C ++ 14, you only need to display the return type of the functions, and, for readability, std::result_of_t<> instead of typename std::result_of<>::type , so we have every chance.

So let's start with the DropArgs() function DropArgs() . It is reasonable to assume that a function must take some arbitrary functor and return some wrapper with an overridden operator() that takes an arbitrary number of arguments. We formulate it:
 namespace detail { template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) //     F_ { f },  clang <3.6  { } template<typename... Args> auto operator() (Args&&... args) { //        } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; } 

We do not yet know how to describe the type returned from operator() , so just leave auto .

What should happen in operator() ? For now, we will think in terms of types: the Args array is divided into two sub- InvokableArgs and Rest such that the functor F can be called with arguments with types from InvokableArgs , and Rest is everything else. For example, for the motivating code at the beginning of the article, InvokableArgs empty for both functors, and Rest is [const Media::IAudioSource*, QModelIndex] and [QModelIndex] respectively (accurate to CV-qualification).

Note that the types passed in operator() do not have to completely coincide with the types that the functor expects (if any), it would be nice to support type conversion as well. For example, if the functor takes a long , and an int passed to our operator() , then it's okay, InvokableArgs = [int] .

Note that if the functor has default arguments, then, generally speaking, the correct partitioning of Args into InvokableArgs and Rest not unique: you can both pass their specific values ​​to the functor (and it will be completely called), and ignore them ( in fact, the default arguments will be substituted):
 auto func = [] (int n, double d, const std::string& s = "hello world", const std::vector<int>& v = {}) {}; auto dropped = DropArgs (func); dropped (1, 3.14); //        : // InvokableArgs = [int, double], Rest = [] dropped (1, 3.14, "bye cruel world", { 1, 2, 3 }); //   : // InvokableArgs = [int, double, std::string, std::vector<int>], Rest = [] // func    n = 1, d = 3.14, s = "bye cruel world", v = { 1, 2, 3 } // //   : // InvokableArgs = [int, double, std::string], Rest = [std::vector<int>] // func    n = 1, d = 3.14, s = "bye cruel world", v = {} // //   : // InvokableArgs = [int, double], Rest = [std::string, std::vector<int>] // func    n = 1, d = 3.14, s = "hello world", v = {} 

For obvious reasons, it makes sense to seek to choose partitions with the maximum InvokableArgs (the first option in the example above).

So, in operator() let's try to figure out the maximum InvokableArgs for this Args .

How can I do that? We can try to call our functor F with the full list of Args . It turned out - well, did not work - bite the type from the end of the list and try again, and so on, until we come to success (or until the types run out, but this will mean that InvokableArgs does not exist for this Args , which is an error) .

Let's write an auxiliary type guardian class (although std::tuple would come down, but I want to avoid overheading guaranteed by making the class empty):
 namespace detail { template<typename...> struct Typelist {}; } 
The only purpose and meaning of life of this class is to keep a specific list of types with which it is instantiated.

Biting off the type from the end of the type list is effectively impossible for O (1) instantiations, as far as I know, the most optimal is O (logn), and even this requires some additional tricks and manipulations, therefore it is left to the reader as an exercise, and we implement a blunt frontal O (n) -algorithm: expand the list, bite off the first element in it and expand it again. And let the compiler puffs!

The bite-off function of the first element looks easy and simple, so let's start with it, calling it Tail in a spirit that is pleasant and understandable to all functionals:
 namespace detail { template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } } 
Note that the return value , as well as the value of the argument, we do not really care about, only their types matter. A similar pattern will haunt us throughout the article. In addition, perhaps, we could immediately agree everywhere to use a specific Typelist instead of the generic argument of the List template, but the above approach seems to be more general.

To rotate the list, we first need the function of pasting two type lists:
 namespace detail { template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } } 

Now it’s possible to expand the list recursively by shifting to C ++ the following suspiciously Haskell-like reverse [] = []; reverse (x:xs) = reverse xs ++ [x] pseudocode reverse [] = []; reverse (x:xs) = reverse xs ++ [x] reverse [] = []; reverse (x:xs) = reverse xs ++ [x] :
 namespace detail { template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } } 
However, not everything is so smooth here, if you go into detail.
Why?
This code does not seem to be a valid C ++ 11 code. The point of a function declaration in C ++ with the presence of a trailing return type specifier is, in fact, the end of the trailing return type specifier, therefore it is impossible to refer to a function inside it. However, for some reason, both gcc and clang happily accept this code. However, we will meet later with similar code that gcc does not accept, and consider one of the ways to get around this problem.

And in C ++ 14 there would be no such problem, because we could rewrite the second function as
  template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) { return Concat (Reverse (List<Tail...> {}), List<Head> {}); } 
and do not know any problems at all: the compiler itself will display the correct type.

Great, now we are ready, finally, to find out the maximum list of types with which our desired functor can still be called. To do this, we write the function GetInvokablePart() , which, when instantiated by our functor and the list of Args types from Dropper::operator() , will have a return type
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
  1. Typelist, .
    template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

    ? SFINAE.

    GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
    , , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

    , Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

    , GetInvokablePart() . operator() :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

    ,
    template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

    C++11 C++14 trailing return type',
    - . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
    template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

    , ? Args , operator() , InvokableArgs . ? , . Dropper :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

    , Rest . ? , , InvokableArgs . :
    template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
    template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
    , Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


    , Dropper :
    template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

    ! , , !

    . gcc :
    prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

    , - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

    , , C++ -, , . , :
    template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

    Invoke :
    template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

    C++11 operator() Invoke , perfect forwarding- .

    . namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


    .


    int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


    int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
    Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

    , , .
  2. Typelist, .
    template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

    ? SFINAE.

    GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
    , , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

    , Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

    , GetInvokablePart() . operator() :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

    ,
    template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

    C++11 C++14 trailing return type',
    - . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
    template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

    , ? Args , operator() , InvokableArgs . ? , . Dropper :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

    , Rest . ? , , InvokableArgs . :
    template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
    template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
    , Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


    , Dropper :
    template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

    ! , , !

    . gcc :
    prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

    , - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

    , , C++ -, , . , :
    template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

    Invoke :
    template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

    C++11 operator() Invoke , perfect forwarding- .

    . namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


    .


    int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


    int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
    Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

    , , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
  1. Typelist, .
    template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

    ? SFINAE.

    GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
    , , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

    , Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

    , GetInvokablePart() . operator() :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

    ,
    template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

    C++11 C++14 trailing return type',
    - . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
    template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

    , ? Args , operator() , InvokableArgs . ? , . Dropper :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

    , Rest . ? , , InvokableArgs . :
    template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
    template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
    , Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


    , Dropper :
    template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

    ! , , !

    . gcc :
    prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

    , - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

    , , C++ -, , . , :
    template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

    Invoke :
    template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

    C++11 operator() Invoke , perfect forwarding- .

    . namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


    .


    int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


    int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
    Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

    , , .
    Typelist, .
    template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

    ? SFINAE.

    GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
    , , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

    , Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

    , GetInvokablePart() . operator() :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

    ,
    template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

    C++11 C++14 trailing return type',
    - . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
    template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

    , ? Args , operator() , InvokableArgs . ? , . Dropper :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

    , Rest . ? , , InvokableArgs . :
    template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
    template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
    , Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


    , Dropper :
    template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

    ! , , !

    . gcc :
    prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

    , - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

    , , C++ -, , . , :
    template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

    Invoke :
    template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

    C++11 operator() Invoke , perfect forwarding- .

    . namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


    .


    int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


    int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
    Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

    , , .
     Typelist,   . 
    template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

    ? SFINAE.

    GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
    , , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

    , Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

    , GetInvokablePart() . operator() :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

    ,
    template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

    C++11 C++14 trailing return type',
    - . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
    template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

    , ? Args , operator() , InvokableArgs . ? , . Dropper :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

    , Rest . ? , , InvokableArgs . :
    template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
    template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
    , Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


    , Dropper :
    template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

    ! , , !

    . gcc :
    prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

    , - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

    , , C++ -, , . , :
    template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

    Invoke :
    template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

    C++11 operator() Invoke , perfect forwarding- .

    . namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


    .


    int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


    int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
    Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

    , , .
  2. Typelist, .
    template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

    ? SFINAE.

    GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
    , , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

    , Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

    , GetInvokablePart() . operator() :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

    ,
    template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

    C++11 C++14 trailing return type',
    - . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
    template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

    , ? Args , operator() , InvokableArgs . ? , . Dropper :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

    , Rest . ? , , InvokableArgs . :
    template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
    template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
    , Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


    , Dropper :
    template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

    ! , , !

    . gcc :
    prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

    , - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

    , , C++ -, , . , :
    template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

    Invoke :
    template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

    C++11 operator() Invoke , perfect forwarding- .

    . namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


    .


    int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


    int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
    Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

    , , .
     Typelist,   . 
    template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

    ? SFINAE.

    GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
    , , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

    , Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

    , GetInvokablePart() . operator() :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

    ,
    template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

    C++11 C++14 trailing return type',
    - . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
    template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

    , ? Args , operator() , InvokableArgs . ? , . Dropper :
    template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

    , Rest . ? , , InvokableArgs . :
    template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
    template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
    , Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


    , Dropper :
    template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

    ! , , !

    . gcc :
    prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

    , - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

    , , C++ -, , . , :
    template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

    Invoke :
    template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

    C++11 operator() Invoke , perfect forwarding- .

    . namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


    .


    int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


    int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
    Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

    , , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
 Typelist,   . 
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .
Typelist, .
template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) { return {}; } template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return {}; }

? SFINAE.

GetInvokablePart() . GetInvokablePartImpl() , ( Args ). , GetInvokablePartImpl() , . ( ):
, , β€” int , β€” float , 0 int . ( std::result_of ) , result_of , , F Args . .

, Args , , GetInvokablePart() Typelist<Args...> . ( Args , β€” , - , , ). , , , , … , , , Args , , , , .

, GetInvokablePart() . operator() :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); } DropArgs() Rest , , gcc GetInvokablePart() . ?

,
template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> decltype (GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list))))) C++: trailing return type specifier , , trailing return type specifier, ( , -> , , ). :

C++11 C++14 trailing return type',
- . template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) { return GetInvokablePartImpl<F> (0, Reverse (Tail (Reverse (list)))); } template<typename F, typename... Args> constexpr auto GetInvokablePart () { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } , , «» . , , . - :
template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); };

, ? Args , operator() , InvokableArgs . ? , . Dropper :
template<typename... Args> auto operator() (Args&&... args) { auto invokableList = GetInvokablePart<F, Args...> (); return Invoke (invokableList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } , InvokableArgs , Rest β€” . , .

, Rest . ? , , InvokableArgs . :
template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } N . :
template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; }
, Drop , , , SFINAE , gcc 4.9 . , , SFINAE . , , .


, Dropper :
template<typename... Args> auto operator() (Args&&... args) { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) { return F_ (std::forward<InvokableArgs> (args)...); } constexpr invokableList , - Drop<Length (decltype (invokableList) {})> .

! , , !

. gcc :
prog.cc: In instantiation of 'void detail::Dropper<F>::operator()(Args&& ...) [with Args = {int&, double}; F = main()::<lambda(int)>]': prog.cc:147:35: required from here prog.cc:125:67: error: no matching function for call to 'detail::Dropper<main()::<lambda(int)> >::Invoke(const detail::Typelist<int&>&, detail::Typelist<double>&, int&, double)' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^ prog.cc:125:67: note: candidate is: prog.cc:129:8: note: template<class ... InvokableArgs, class ... Rest> void detail::Dropper<F>::Invoke(detail::Typelist<InvokableArgs ...>, detail::Typelist<Rest ...>, InvokableArgs&& ..., Rest&& ...) [with InvokableArgs = {InvokableArgs ...}; Rest = {Rest ...}; F = main()::<lambda(int)>] void Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, InvokableArgs&&... args, Rest&&...) ^ prog.cc:129:8: note: template argument deduction/substitution failed: prog.cc:125:67: note: inconsistent parameter pack deduction with '' and '' Invoke (invokableList, ignoreList, std::forward<Args> (args)...); ^

, - inconsistent parameter pack deduction with '' and '' , gcc InvokableArgs ( Typelist ), . ?

, , C++ -, , . , :
template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; Dumbify<Args...> - Args... , .

Invoke :
template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) { return F_ (std::forward<InvokableArgs> (args)...); }

C++11 operator() Invoke , perfect forwarding- .

. namespace detail { template<typename... Args> struct Typelist { }; template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } template<int N, typename List> struct DropImpl { using Result_t = typename DropImpl<N - 1, decltype (Tail (List {}))>::Result_t; }; template<typename List> struct DropImpl<0, List> { using Result_t = List; }; template<int N, template<typename...> class List, typename... Args> constexpr typename DropImpl<N, List<Args...>>::Result_t Drop (List<Args...>) { return {}; } template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } template<template<typename...> class List> constexpr List<> Reverse (List<>) { return {}; } template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) -> decltype (Concat (Reverse (List<Tail...> {}), List<Head> {})) { return {}; } template<typename F, template<typename...> class List, typename... Args> constexpr List<Args...> GetInvokablePartImpl (int, List<Args...>, typename std::result_of<F (Args...)>::type* = nullptr) { return {}; } template<typename F, template<typename...> class List> constexpr Typelist<> GetInvokablePartImpl (float, List<>) { return {}; } template<typename F, typename List> struct InvokableType; template<typename F, template<typename...> class List, typename... Args> constexpr auto GetInvokablePartImpl (float, List<Args...> list) -> typename InvokableType<F, decltype (Reverse (Tail (Reverse (list))))>::RetType_t { return {}; } template<typename F, typename List> struct InvokableType { using RetType_t = decltype (GetInvokablePartImpl<F> (0, List {})); }; template<typename F, typename... Args> constexpr auto GetInvokablePart () -> decltype (GetInvokablePartImpl<F> (0, Typelist<Args...> {})) { return GetInvokablePartImpl<F> (0, Typelist<Args...> {}); } template<template<typename...> class List, typename... Args> constexpr size_t Length (List<Args...>) { return sizeof... (Args); } template<typename T> struct Dumbifier { using Type_t = T; }; template<typename T> using Dumbify = typename Dumbifier<T>::Type_t; template<typename F, typename List> struct InvokableResGetter; template<typename F, template<typename...> class List, typename... Args> struct InvokableResGetter<F, List<Args...>> { using RetType_t = typename std::result_of<F (Args...)>::type; }; template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f) { } template<typename... Args> auto operator() (Args... args) -> typename InvokableResGetter<F, decltype (GetInvokablePart<F, Args...> ())>::RetType_t { constexpr auto invokableList = GetInvokablePart<F, Args...> (); auto ignoreList = Drop<Length (invokableList)> (Typelist<Args...> {}); return Invoke (invokableList, ignoreList, std::forward<Args> (args)...); } private: template<typename... InvokableArgs, typename... Rest> auto Invoke (Typelist<InvokableArgs...>, Typelist<Rest...>, Dumbify<InvokableArgs>... args, Dumbify<Rest>...) -> typename std::result_of<F (InvokableArgs...)>::type { return F_ (std::forward<InvokableArgs> (args)...); } }; } template<typename F> detail::Dropper<F> DropArgs (const F& f) { return detail::Dropper<F> { f }; }


.


int Bar () { return DropArgs ([] (int n) { return n * 2; }) (1, 2.5); } , gcc 4.8+, , , return 2 , clang 3.3+. . icc 13.0, , .


int Bar () { volatile int n = 1; return DropArgs ([] (int n) { return n * 2; }) (n, 2.5); } -
Bar(): movl $1, -4(%rsp) movl -4(%rsp), %eax addl %eax, %eax ret

, , .

Source: https://habr.com/ru/post/264157/


All Articles