2012-01-22 121 views
2

我想實現我自己的is_member_function_pointer,我遇到了麻煩。is_member_function_pointer implementation

namespace __implementation 
{ 
    // integral_constant 
    template<typename T, T v> 
    struct integral_constant 
    { 
     static constexpr T result = v; 
     typedef integral_constant<T,v> type; 
     constexpr operator T() { return result; } 
    }; 
    // true_type 
    typedef integral_constant<bool, true> true_type; 
    // false_type 
    typedef integral_constant<bool, false> false_type; 
    // remove_const 
    template<typename T> struct remove_const { typedef T type; }; 
    template<typename T> struct remove_const<const T> { typedef T type; }; 
    // remove_volatile 
    template<typename T> struct remove_volatile { typedef T type; }; 
    template<typename T> struct remove_volatile<volatile T> { typedef T type; }; 
    // remove_cv 
    template<typename T> struct remove_cv 
    { typedef typename remove_volatile<typename remove_const<T>::type>::type type; }; 
    // is_function - ugliness ahead due to variadic functions! 
    template<typename T, typename... Args> struct is_function : public false_type {}; 
    template<typename T, typename... Args> struct is_function<T(Args...)> : public true_type {}; // normal function 
    template<typename T, typename... Args> struct is_function<T(Args......)> : public true_type {}; // variadic function 
    // is_member_function_pointer 
    template<typename T> struct is_member_function_pointer : public false_type {}; 
    template<typename T, typename Class> struct is_member_function_pointer<T Class::*> : public is_function<T> {}; 
} 
/* 
* Short forms: either alias templates or constexpr functions 
*/ 
// remove_const 
template<typename T> 
using remove_const = typename __implementation::remove_const<T>::type; 
// remove_volatile 
template<typename T> 
using remove_volatile = typename __implementation::remove_volatile<T>::type; 
// remove_cv 
template<typename T> 
using remove_cv = typename __implementation::remove_cv<T>::type; 
// is_member_function_pointer 
template<typename T> 
constexpr bool is_member_function_pointer { return __implementation::is_member_function_pointer<T>::result; } 
// is_function 
template<typename T> 
constexpr bool is_function() { return __implementation::is_function<typename __implementation::remove_cv<T>::type>::result; } 

問題在於正常的函數指針,它無法像爲member_function_pointer模板一樣工作。此外,const成員函數指針不被識別爲member_function_pointer,這是不幸的。我該如何解決這個問題?我相信我可以enable_if一個正常的函數指針專門化,以解決正常的函數指針問題,但我看不到一個出來的const成員函數指針問題的一種方式(我已經字面上嘗試添加類型trait中的remove_cv和const的無處不在定義,無濟於事)。我可以看到當前is_member_function_pointer沒有處理const類的成員函數,但我不知道我可以使用什麼語法。

任何幫助表示讚賞。

+2

'__implementation'肯定是一個保留的標識符(兩個下劃線)。 – UncleBens

+0

@UncleBens哦,是的,但我完全繞過標準庫,所以我並不在乎。如果它爆炸在我的臉上,我會解決它。 – rubenvb

回答

4

上聊天很短的談話已經把這個簡單的解決方案:

// is_member_function_pointer 
template<typename T> struct is_member_function_pointer : public false_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...)> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) const> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) volatile> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) const volatile> : public true_type {}; 

其中包括volatile專業化爲好。

編輯爲@Xeo和@Johannes指出,我錯過了裁判修飾符(又名右值的*此)版本:

template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) &> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) const &> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) volatile &> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) const volatile &> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) &&> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) const &&> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) volatile &&> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...) const volatile &&> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...)> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) const> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) volatile> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) const volatile> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) &> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) const &> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) volatile &> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) const volatile &> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) &&> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) const &&> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) volatile &&> : public true_type {}; 
template<typename T, typename Class, typename... Args> struct is_member_function_pointer<T (Class::*)(Args...,...) const volatile &&> : public true_type {}; 

這仍然是相當可行的。它更清晰,然後瘋狂的模板魔術和衆多的幫手模板恕我直言。

EDIT2澄清,以上都是在執行命名空間和

template<typename T> constexpr bool 
is_member_function_pointer() { return __implementation::is_member_function_pointer<remove_cv<T>>::result; } 

remove_cv的別名template'd以方便

template<typenamen T> using 
remove_cv = typename __implementation::remove_cv<T>::type; 

我想有纏其他的,也許更好的方法,但這個至少清晰的讀者沒有任何進一步的SFINAE技巧,如應用在libC++或libstdC++,恕我直言。

+0

現在請爲ref-qualifiers。 :)這增加了另外8個專業IIRC。 :D – Xeo

+0

總共需要96個特化才能支持c/v(在成員指針和函數類型上),「...」和我相信的ref-qualifiers的所有組合。不值得使用該方法。因此,顯示所有「功能開啓」(帶有'&')時的樣子:T(Class :: * const volatile)(Args ......)const volatile&'。 –

+0

@Xeo這裏不是旁路討論這個問題,但Boost的測試不測試任何cv-qualified成員函數指針,更不用說引用了。這些有多重要? – rubenvb

2

備選地

template<typename T> struct remove_c { typedef T type; }; 
template<typename T> struct remove_c<T const> { typedef T type; }; 

template<bool C> 
struct bool_ { static bool const value = C; }; 

template<typename T, typename U> 
struct is_same : bool_<false> {}; 

template<typename T> 
struct is_same<T, T> : bool_<true> { }; 

template<typename T, typename = bool_<true> > 
struct is_function : bool_<false> {}; 

struct C { }; 

template<typename T> 
struct is_function< T, 
    bool_<is_same<typename remove_c<T>::type const C::*, 
       typename remove_c<T>::type  C::*>::value> > 
    : bool_<true> {}; 

template<typename T> 
struct is_member_function_pointer_impl : bool_<false> {}; 

template<typename T, typename C> 
struct is_member_function_pointer_impl<T C::* const volatile> 
    : is_function<T> {}; 

template<typename T> 
struct is_member_function_pointer 
    : is_member_function_pointer_impl<T const volatile> {};