コンテンツにスキップ

最終更新: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 の引数の個数を取得する機能が実現できました〜

関連トピック

コメント