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.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");
.DropArgs ([] (int n) { return n; }) (0, 3.14, "foobar");
. std::result_of_t<>
instead of typename std::result_of<>::type
, so we have every chance.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 }; }
operator()
, so just leave auto
.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).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]
.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 = {}
InvokableArgs
(the first option in the example above).operator()
let's try to figure out the maximum InvokableArgs
for this Args
.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) .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.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. namespace detail { template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } }
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. 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.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
, , .
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
, , .
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