2016-07-20 4 views
2

クラスを変換可能な関数ポインタ型の戻り値の型と引数の型を抽出するテンプレートを記述することは可能ですか?例:他の変換演算子を持っていないと間接演算子を定義していない変換演算子から関数ポインタへの戻り値と引数型の抽出

struct Foo { 
    using FnPtr = int (*)(char, double); 

    operator FnPtr() const { ... } 
}; 

// Can I extract the return type (int) and argument types (char and double), 
// knowing only `Foo` as an opaque type? 

答えて

6

Foo場合、あなたは*a_fooは、所望の種類の関数への参照を与えるという事実に頼ることができます。それでは、あなたは戻り値と引数を抽出するだけです。ここ

func_ref_traitsは抽出を行います。

template <typename Func> 
struct func_ref_traits; 

template <typename Ret, typename... Args> 
struct func_ref_traits<Ret(&)(Args...)> { 
    using ret = Ret; 
    using args = std::tuple<Args...>; 
}; 

その後conv_func_traitsは、指定された型から関数型をうまくいく:

template <typename T> 
using conv_func_traits = func_ref_traits<decltype(*std::declval<T>())>; 

あなたはそうのように、これを使用します。

conv_func_traits<Foo>::args //std::tuple<char,double> 
conv_func_traits<Foo>::ret //int 
+0

私はこれがおそらく最高のものだと思います。ありがとう! –

3

ここに行きます:

#include <type_traits> 

template <typename...> struct typelist; 

template <typename> struct Extract; 

template <typename R, typename ...Args> 
struct Extract<R(*)(Args...)> 
{ 
    using Result = R; 
    using Arguments = typelist<Args...>; 
}; 



template <typename T> 
using Return_Type = typename Extract<typename T::FnPtr>::Result; 

template <typename T> 
using Arguments = typename Extract<typename T::FnPtr>::Arguments; 




struct Foo 
{ 
    using FnPtr = int (*)(char, double); 
}; 


int main() 
{ 
    static_assert(std::is_same<Return_Type<Foo>, int>::value, ":("); 
    static_assert(std::is_same<Arguments<Foo>, typelist<char, double>>::value, ":("); 
} 

引数を表すためにタイプリストを使用しましたが、その方が良い場合はstd::tupleを使用できます。さらに、さまざまな種類の呼び出し可能なものをカバーするために、Extractのさらに特殊化が必要な場合があります。

+1

しかし、 'Foo'は* opaque *型としてしか知られていないので、残念ながら私は' FnPtr'パーツを使用できません。 –