2016-11-01 11 views
1

ショートバージョンタイプを推測したいと思います:入力する必要が常に私はメンバ関数へのポインタから、C++テンプレートで

の代わりに:

auto function_pointer = &decorator<int, Foo, void &Foo::bar(int)> 

を私ができるようにしたいと思いますただintFooが自動的にから抽出され

auto function_pointer = &decorator<void &Foo::bar(int)> 

を書き込みます>。

私は手始めに

map<string, Object*> all_object_instances; 

class Object { 
public: 
    Object(const string &name) { all_object_instances[name]=this; } 
    virtual ~Object() { all_object_instances.erase(name); } 
}; 

class Foo : public Object { 
public: 
    Foo(const string &name) : Object(name) {} 
    void bar(int); 
}; 

私はいくつかの装飾ではFoo ::バー(INT)を呼び出す機能を、必要とするので、私は書く:

template <class Arg, class C, void C::*T(Arg)> 
void decorator(const string &name, const string &s_arg) 
{ 
    Arg a = my_convert(s_arg); 
    C* c = dynamic_cast<C*>(all_object_instances[name]); 
    (c->*T)(a); 
} 

私のメインコードはこのようにしなければなりません:

new Foo("MyFoo"); 
    .... 
    auto saved_f = &decorator<int, Foo, void &Foo::bar(int)>; 
    .... 
    saved_f("MyFoo", "123"); 
    .... 
    delete all_object_instances("MyFoo") // for symmetry 

私はちょうど1つのテンプレート引数持つことができればそれは、多くの方のようになります。

saved_f = &decorator<void &Foo::bar(int)>; 

そして両方'foo' で、および"int型引数からの導出:

template <TEMPLATE MAGIC> 
void decorator(const string &name, const string &s_arg) 
{ 
    typedef ARG_MAGIC ARG; 
    typedef CLASS_MAGIC C; 

    Arg a = my_convert(s_arg); 
    C* c = dynamic_cast<C*>(all_object_instances[name]); 
    (c->*T)(a); 
} 

このようなことはありますか?

+0

私が編集した質問:

template <typename> struct method_traits; template <typename Ret, typename Class, typename ... Args> struct method_traits<Ret (Class::*)(Args...)> { using ret_type = Ret; using classe_type = Class; using args_type = std::tuple<Args...>; }; 

それで最後に:次に

あなたは、のような何かをするクラスを取得し、型を返すためにいくつかの機能の特徴を必要としますよりシンプルで明確ですか?私の「ショートバージョン」は正しいですか?もしそうなら、質問の残りの部分はほとんど無関係であるので、大幅に簡素化(または削除すること)を考慮する必要があります。 –

+0

はい、それは素晴らしい改訂です。私は長いバージョンを残しておきたいと思います。なぜなら、時々問題の私の刺しは間違っていたからです:) ありがとうtho – dandax

+0

メンバ関数のポインタ型を指定するだけで2つのテンプレートパラメータに絞り込むことができますが、私が言うことができるように、[関数ポインタのテンプレート引数の型を推論する方法はありません](http://stackoverflow.com/questions/17736337/is-there-a-way-to-deduce-the-value-of -a-function-pointer-template-parameter)を使用します。しかし、その答えに応じて、あなたは*(*私は知っている/)マクロを作ることができます。それ以降は、戻り値、クラス、および引数の型を見つけることの唯一の問題です。(http://coliru.stacked-crooked.com/a/a577f71af2697f16) – jaggedSpire

答えて

0

関数を引数として渡すと、その関数を呼び出すことができます。それは単にテンプレート引数の控除によって推測することができます。

以下の例では、私はちょうど汎用性を追加しました。引数をstd::invokeに渡しました。これは自動的にメンバーへのポインタを呼び出すことができます。これは<functional>で見つけることができますstd::invokeのためのC++ 1yの対応のコンパイラを必要とし、

auto saved_f = decorator(&Foo::bar); 
saved_f("MyFoo", "123"); 

:今、これがに縮小され

template<class R,class C,class... Args> 
auto get_class_type(R(C::*)(Args...))->C; 

template<class F> 
auto decorator(F f) { 
    return [f=move(f)](auto const& name, auto const& arg) { 
    using C=decltype(get_class_type(f)); 
    return std::invoke(move(f), 
     dynamic_cast<C*>(all_object_instances[name]), 
     my_convert(arg) 
    ); 
    }; 
} 

。あなたの目標は、テンプレート引数は定数、コンパイル時間が持っているのであれば、それも可能です

auto c = dynamic_cast<C*>(all_object_instances[name]); 
return (c->*move(f))(my_convert(arg)); 

:これはあなたのためにコンパイルされない場合は、単純にそれを変更します。

#define decorator(mem_f) decorator_impl(integral_constant<decltype(mem_f), mem_f>{}) 

その後のタイプのうちの値を抽出します:あなたがマクロを使用してdecoratorintegral_constantを渡す必要があります。この場合、C++ 1Zで

template<class I> 
auto decorator_impl(I) { 
    auto constexpr f = I::value; 
    // same code as before... 
} 
+0

これを解読してください。 テンプレート<クラスR、クラスC、クラス... Args> auto get_class_type(R(C :: *)(Args ...)) - > C; 私はテンプレート関数、クラス、または(C++ 1xで)を使用して知っています – dandax

+0

@dandax関数テンプレートの宣言です。 'Args ...'を引数とし、 'R'型を返す' C'クラスのメンバ関数へのポインタを引数としてとります。私はクラスCの型を返すだけです( 'auto(...) - > C'を実行して) – 0x499602D2

+0

どう違うのですか? テンプレート<クラスR、クラスC、クラス...Args> C get_class_type(R(C :: *)(Args ...)); – dandax

-1

を、あなたはできるはずです希望構文

auto saved_f = &decorator<void &Foo::bar(int)> 

template <auto m> 
void decorator(const string &name, const string &s_arg); 

を書き込みます構文

auto saved_f = &decorator<decltype(&Foo::bar), &Foo::bar>; 

またはバージョンと

代わりの

template <typename M, M m> 
void decorator(const string &name, const string &s_arg); 

。ずっとそれを作るために試みで

template <auto m> 
void decorator(const string &name, const string &s_arg) 
{ 
    using C = typename method_traits<decltype(m)>::class_type; 
    using Arg = std::tuple_element_t<0, typename method_traits<decltype(m)>::args_type>; 

    Arg a = my_convert(s_arg); 
    C* c = dynamic_cast<C*>(all_object_instances[name]); 
    (c->*T)(a); 
} 
+1

リリースされたバージョンでは、どのコンパイラも 'auto'テンプレートパラメータをサポートしていますか?ステータスはgccでは "No"、clangでは "SVN"と表示されます。 – jaggedSpire

+0

式 'void&Foo :: bar(int)'はどういう意味ですか? –

+0

どのように 'を使用してC = typename method_traits :: class_type;'仕事?クラスの暗黙的な引数は、後のC++標準で動作するようになりましたか? – dandax

関連する問題