2012-12-21 105 views
1

數量和類型:確定的參數和類型參數的返回類型是給定C++ 11功能的功能

X f(A, B, C); 

反正有從該函數內:

template<typename T> 
void g(T t) 
{ 
    ... 
} 

調用如下:

g(f); 

確定:

  • F的
  • 的參數參數i的類型的編號f
  • F的

...

template<typename F> 
void g(F f) 
{ 
    constexpr size_t n = num_params<F>::n; // 3 
    return_type<F>::type x; // X 
    tuple<param_types<F>::type...> a; // tuple<A, B, C> 
} 

返回類型?

+0

您正在尋找的東西'__PRETTY_FUNCTION__'在海灣合作委員會和其他編譯器? –

+0

@MatsPetersson:'__PRETTY_FUNCTION__'是在預處理時產生的字符串 - 我需要使用類型,因爲我會模板類型參數,而不僅僅是打印他們的名字。 –

+0

你的問題的意圖並不完全清楚(正如所表達的,完全有可能你在腦海中有一個好主意 - 我經常遭受這種困擾!) –

回答

7

肯定的:

template <typename R, typename ...Args> 
void g(R(&f)(Args...)) 
{ 
    typedef R return_type; 
    unsigned int const n_args = sizeof...(Args); 

    // ... 
} 

用法:

int foo(char, bool); 

g(foo); 
+0

這將與lamdbas綁定表達式和std :: function作爲輸入嗎?f前的'&'符號的含義是什麼? –

+0

以上代碼適用於實際功能。但它不適用於函數對象。一般來說,對於函數對象來說,它可能無法工作,因爲它可能有多個函數調用操作符,並且沒有足夠的上下文來確定要調用哪一個操作符。 –

+0

你也可以提供'std :: function'的重載,也就是'g(std :: function const&f)'... Lambdas然後將通過隱式轉換工作。 –

2

這是我從來對工作你想要做什麼,我認爲 - 但它僅限於定義最多一個函數調用操作符函子(lambda符合這個限制)。它也適用於MSVC 2012 CTP。

namespace detail { 
    //////////////////////////////////////////////////////////////////////////// 
    //! Select between function pointer types 
    //////////////////////////////////////////////////////////////////////////// 
    template <typename T> 
    struct callable_helper_ptr; 

    //! non-member functions 
    template <typename R, typename... Args> 
    struct callable_helper_ptr<R (*)(Args...)> { 
     typedef void    object_t; 
     typedef R     result_t; 
     typedef std::tuple<Args...> args_t; 
    }; 

    //! member functions 
    template <typename R, typename O, typename... Args> 
    struct callable_helper_ptr<R (O::*)(Args...)> { 
     typedef O     object_t; 
     typedef R     result_t; 
     typedef std::tuple<Args...> args_t; 
    }; 

    //! const member functions 
    template <typename R, typename O, typename... Args> 
    struct callable_helper_ptr<R (O::*)(Args...) const> { 
     typedef O     object_t; 
     typedef R     result_t; 
     typedef std::tuple<Args...> args_t; 
    }; 

    //////////////////////////////////////////////////////////////////////////// 
    //! Select between function pointers and functors 
    //////////////////////////////////////////////////////////////////////////// 
    template <typename T, typename is_ptr = typename std::is_pointer<T>::type> 
    struct callable_helper; 

    //! specialization for functors (and lambdas) 
    template <typename T> 
    struct callable_helper<T, std::false_type> { 
     typedef callable_helper_ptr<decltype(&T::operator())> type; 
    }; 

    //! specialization for function pointers 
    template <typename T> 
    struct callable_helper<T, std::true_type> { 
     typedef callable_helper_ptr<T> type; 
    }; 
} //namespace detail 

//////////////////////////////////////////////////////////////////////////////// 
//! defines the various details of a callable object T 
//////////////////////////////////////////////////////////////////////////////// 
template <typename T> 
struct callable_traits { 
    typedef typename detail::callable_helper<T>::type::object_t object_t; 
    typedef typename detail::callable_helper<T>::type::result_t result_t; 
    typedef typename detail::callable_helper<T>::type::args_t args_t; 

    template <unsigned N> 
    struct arg : public std::tuple_element<N, args_t> {}; 
}; 

而且我寫了對過程背後寫如果有人有興趣: http://bkentel.wordpress.com/2012/12/12/defining-a-traits-type-for-callable-objects/

相關問題