こんにちは、Habr。
ある日曜日のある晴れた日の午後、
プロジェクトの1つにコードを書き
ました 。 単純化するために、コードは次のようになりました。
const bool exists = WithObject (objectId, [] (const Media::IAudioSource*, const QModelIndex&) { return true; }, [] (const QModelIndex&) { return false; });
WithObjectは、IDによってオブジェクトを見つけようとし、見つかった場合は最初のファンクターを実行し、見つからない場合は2番目のファンクターを実行します。 これは、実行されたファンクターが返した値を返します(2番目のファンクターの戻り値の型が最初のファンクターの型にキャストされることが理解されます)。 この場合、検索中に取得された有用な情報(たとえば、オブジェクト自体)はファンクターに送信されます。
したがって、上記のコードはオブジェクトの存在を確認するだけであり、
WithObjectがファンクターに渡す引数は必要ありません。 そのため、このようなコードを作成するために、このような
DropArgs()関数を作成するとよいと思いました
const bool exists = WithObject (objectId, DropArgs ([] { return true; }), DropArgs ([] { return false; }));
正しかった。 または、
DropArgs ([] { return false; }) (0, 3.14, "foobar"); 。
また、最初のN個の引数のみが必要な場合、残りも省略できます
DropArgs ([] (int n) { return n; }) (0, 3.14, "foobar"); 。
C ++ 14では、可能な限りC ++ 11との互換性を維持しようと考えています。 実際、C ++ 14からは、関数の戻り値の型を出力するだけでよく、読みやすくするために、
typename std::result_of<>::typeではなく、あらゆる種類の
std::result_of_t<>使用するため、あらゆる機会があります。
それでは、
DropArgs()関数
DropArgs()から始めましょう。 関数が任意のファンクターを取り、任意の数の引数を取るオーバーライドされた
operator()でラッパーを返す必要があると仮定するのは合理的です。 これを述べます:
namespace detail { template<typename F> class Dropper { F F_; public: Dropper (const F& f) : F_ (f)
operator()から返される型を記述する方法はまだわからないため、
autoままにしておきます。
operator()で何が起こるべきですか? ここでは、型の観点から考えます
Args配列は、問題の条件によって
InvokableArgsと
Rest 2つの
InvokableArgs配列に分割されます。このため、ファンクタFは
InvokableArgs型の引数で呼び出すことができますが、
Restは残りです。 たとえば、記事の冒頭の動機付けコードでは、
InvokableArgs両方のファンクターに対して空であり、
Restはそれぞれ
[const Media::IAudioSource*, QModelIndex]および
[QModelIndex] (CV修飾に正確)です。
operator()渡される型は、ファンクターが予期する型(存在する場合)と完全に一致する必要はないことに注意してください。型変換も適切にサポートするのが良いでしょう。 たとえば、ファンクターが
long受け入れ、
operator() intを渡した場合、
InvokableArgs = [int]問題あり
InvokableArgs = [int] 。
ファンクタにデフォルト引数がある場合、一般的に言えば、
InvokableArgsと
Rest正しく分割することは一意で
Restないことに注意してください。特定の値をファンクタに渡し(完全に呼び出し可能)、それらを無視できます(同時に、実際、デフォルトの引数が置換されます):
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が最大のパーティション(上記の例の最初のオプション)を選択するのは理にかなっています。
そのため、
operator()この
InvokableArgsの最大
InvokableArgsを見つけてみましょう。
これをどのように行うことができますか?
Argsなリストを
Argsして、ファンクターFを呼び出すことができ
Args 。 それは判明しました-うまくいきませんでした-リストの最後からタイプを噛んで、成功するまで(または、タイプがなくなるまで、これは
InvokableArgsがこの
InvokableArgs存在しないことを意味し、エラーがあることを意味します) 。
補助的なクラスガーディアンクラスを記述します(
std::tupleはなくなりますが、クラスを空にしてオーバーヘッドを回避することを保証したい):
namespace detail { template<typename...> struct Typelist {}; }
このクラスのライフの唯一の目的と意味は、インスタンス化される特定のタイプのリストを保存することです。
私が知る限り、O(1)インスタンスの型のリストの最後から型を噛むことは不可能であり、最も最適なのはO(logn)であり、それでもいくつかの追加のトリックと操作が必要なので、演習として読者に任され、鈍い前頭を実装しますO(n)-アルゴリズム:リストを展開し、リストの最初の要素を噛み砕いて、再度展開します。 そして、コンパイラにパフをしましょう!
最初の要素を食い止める機能は簡単で単純に見えるので、それから始めましょう。すべての機能者にとって快適で理解しやすい方法で
Tailを呼び出します。
namespace detail { template<template<typename...> class List, typename H, typename... T> constexpr List<T...> Tail (List<H, T...>) { return {}; } }
戻り
値と引数の
値は完全にわずらわされず、型のみが重要であることに注意してください。 同様のパターンは、記事全体を通して私たちを悩ませます。 さらに、
Listテンプレートの一般化された引数の代わりに、
Typelist具体的な
Typelistを使用することにすぐに同意できるかもしれませんが、上記のアプローチはより一般的なようです。
リストを展開するには、最初に2つのタイプのリストを接着する機能が必要です。
namespace detail { template<template<typename...> class List, typename... Args1, typename... Args2> constexpr List<Args1..., Args2...> Concat (List<Args1...>, List<Args2...>) { return {}; } }
Haskellの擬似コード
reverse [] = []; reverse (x:xs) = reverse xs ++ [x]疑わしく似た以下をC ++にシフトすることで、リストを再帰的に展開でき
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 {}; } }
ただし、ささいなことをすれば、すべてがそれほどスムーズではありません。
なんで?このコードは有効なC ++ 11コードではないようです。 末尾の戻り値の型指定子が存在する場合のC ++の関数宣言ポイントは、実際には、末尾の戻り値の型指定子の終わりなので、その中の関数を参照することはできません。 ただし、何らかの理由で、gccとclangの両方がこのコードを喜んで受け入れます。 ただし、少し後で、gccが受け入れない同様のコードに出会い、この問題を回避する方法の1つを検討します。
C ++ 14では、2番目の関数を次のように書き換えることができるため、このような問題は発生しません。
template<template<typename...> class List, typename Head, typename... Tail> constexpr auto Reverse (List<Head, Tail...>) { return Concat (Reverse (List<Tail...> {}), List<Head> {}); }
問題をまったく知らない:コンパイラは正しい型を推測します。
さて、ファンクタを呼び出すことができる型の最大リストを最終的に見つける準備ができました。 これを行うために、
GetInvokablePart()関数を作成します。この関数は、ファンクターと、
Dropper::operator()の
GetInvokablePart()タイプリストによってインスタンス化され、戻り値の型を持ちます。
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
, , .