最終更新:2026-10-12
ある面白い C++ コード¶
0.はじめに¶
目標:lambda または functor の引数の個数を取得するには?
この節では、テンプレート+::*+decay+decltype で実現します!
1.実装¶
最終的な効果:
auto c1 = [](int x, double y) { return x * y; };
std::cout << argument_count<decltype(c1)>::value << std::endl;
MyClass f;
std::cout << argument_count<decltype(f)>::value << std::endl;
出力:2
この問題について考えてみましょう。次のいくつかのポイントを押さえる必要があります:
- functor と lambda の位置をどのように特定するか?
- この関数シグネチャの引数の数をどのように取得するか?
最初の問題については、::* を使えばメンバ宣言を指すことができます。functor でも lambda でも &std::decay<F>::type::operator()) です。簡単に言えば、どちらも operator() という宣言のアドレスを取得します。
ここでは decay を使って cv 修飾子を除去します。上の MyClass を例にとると、まず std::decay<F>::type で MyClass 型を取得し、続いて対応する operator() のアドレスを取得して、argument_count_impl に渡します。
template <typename F>
using argument_count = decltype(argument_count_impl(&std::decay<F>::type::operator()));
argument_count_impl の実装も比較的シンプルです。R (F::*)(A...) というシグネチャで対応する関数を取得します。ここでは可変引数テンプレート、::*、sizeof を使って引数の数を取得します。integral_constant は、このコンパイル時定数の型が int で値が sizeof...(A) であることを表します。
template <typename F, typename R, typename... A>
static std::integral_constant<int, sizeof...(A)> argument_count_impl(R (F::*)(A...));
これに基づいて、Lambda または Functor の引数の個数を取得する機能が実現できました〜
関連トピック¶
- C++ 文字列の 6 つの分割方法 | C++那些事
- CPython 拡張開発メモ | C++那些事
- libcurl C++ 開発メモ | C++那些事
- オープンソース C++ コードの読み方 | C++那些事
- C++ ループなしで 1-100 を出力 | C++那些事