3

別の質問に触発されて、その関数を呼び出すために使用される実際の引数を指定して、オーバーロード メンバー関数の型を推測する方法を見つけようとしました。これが私がこれまでに持っているものです:

#include <type_traits>

template<typename F, typename Arg>
struct mem_fun_type {
  // perform overload resolution here
  typedef decltype(std::declval<F>()(std::declval<Arg>())) result_type;
  typedef decltype(static_cast<result_type (F::*)(Arg)>(&F::operator())) type;
};

struct foo {};

struct takes_two
{
  void operator()(int);
  void operator()(foo);
};

struct take_one {
  void operator()(float);
};

int main()
{
  static_assert(std::is_same<mem_fun_type<take_one, float>::type, 
                             void (take_one::*)(float)>::value, "Zonk");
  static_assert(std::is_same<mem_fun_type<takes_two, double>::type, 
                             void (takes_two::*)(float)>::value, "Zonk");
  return 0;
}

テンプレート パラメーター Arg が実際の型と一致する限り、static_cast は成功しますが、これはオーバーロード解決 (完全一致) の最も単純なケースにすぎません。テンプレートのメタプログラミングで完全なオーバーロード解決プロセスを実行することは可能ですか?

これは純粋に仮説であり、実際の使用を意図したものではありません。

4

1 に答える 1

1

これは、これまでのところ最も近いものです。さまざまなサイズのテーブルを返す関数を定義すると、結果はsizeof(select(...))、一致させたい関数へのポインターを受け取ります。function が特定のクラスに存在しない場合でもコードがコンパイルされるようにするには、別の check を使用できますhas_function

過負荷解決の結果は にありselect<has_function<T>::value, T>::valueます。

このコードを使用すると、関数だけでなくデータメンバーを「解決」することもできます。選択関数の正しいパラメーターを作成するだけの問題です。

ただし、ここには 1 つの欠点があります。オーバーロードの解決は、関数のパラメーターではなく、関数の型です。つまり、通常のパラメーターの型変換は行われません。

  // Verify the name is valid
  template <typename T>
  struct has_function
  {
    struct F {int function;};
    struct D : T, F {};
    template <typename U, U> struct same_;
    template <typename C> static char(&select_(same_<int F::*, &C::function>*))[1];
    template <typename> static char(&select_(...))[2];
    enum {value = sizeof(select_<D>(0)) == 2};
  };

  // Values to report overload results
  enum type { none=1 , function_sz_size_t , function_sz , function_string };

  template <bool, typename R> struct select;

  template <typename R> struct select<false, R>
  {
    enum {value = none};
  };

  template <typename R> struct select<true, R>
  {
    // Define your overloads here, they don't have to be templates.
    template <typename Ret, typename Arg> static char(&select_(Ret (R::*)(const char*, Arg)))[function_sz_size_t];
    template <typename Ret, typename Arg> static char(&select_(Ret (R::*)(Arg)))[function_sz];
    template <typename Ret> static char(&select_(Ret (R::*)(std::string)))[function_string];
    template <typename Ret> static char(&select_(Ret (R::*)(std::string&&)))[function_string];
    template <typename Ret> static char(&select_(Ret (R::*)(const std::string&)))[function_string];
    static char(&select_(...))[none];
    enum {value = sizeof(select_(&R::function))};
  };
于 2012-01-20T02:26:23.433 に答える