2012-01-20 9 views
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は成功しますが、これが唯一の オーバーロードの解決(完全一致)の最も平凡なケースである:ここでは私がこれまで持っているものです。テンプレートメタプログラミングで 完全なオーバーロード解決プロセスを実行することは可能ですか?

これはまったく仮定的であり、実際の使用には向いていません。

+0

これは純粋な実例です。私は昨日、「boost :: bind-vs-std :: bind」の問題でそれを打ちました! – vines

+2

私はここであなたが話した質問に答えました(http://stackoverflow.com/a/8938409/147192)。クライアントの助けがなければ、私はちょうど過負荷の解決について推論する方法を見ない。 –

+0

あなたは処罰のための大食犬です。 –

答えて

1

これまで私がこれまでに行ったことは、さまざまなサイズのテーブルを返す関数を定義することでした。結果はsizeof(select(...))と一致する関数へのポインタを受け取ります。指定されたクラスに関数が存在しなくてもコードがコンパイルされるようにするには、別のチェック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))}; 
    }; 
関連する問題