2013-03-05 25 views
11

Jak wykryć funkcję elementu ma modyfikator const, czy nie?Ustalanie stałości funkcji elementu

Rozważmy kod

struct A { 
    int member(); 
    int member() const; 
}; 

typedef int (A::*PtrToMember)(); 
typedef int (A::*PtrToConstMember)() const; 

muszę coś takiego:

std::is_const<PtrToMember>::value // evaluating to false 
std::is_const<PtrToConstMember>::value // evaluating to true 
+1

Czy nie znasz typów danych, z którymi masz do czynienia podczas pisania kodu? –

+1

nie są constness funkcji członkowskich sprawdzane w czasie kompilacji? – zzk

+2

@EdHeal Co jeśli jest to szablonowy argument? Wtedy nie wiesz, aż do powstania. Wyobraź sobie, że chcesz go użyć w 'enable_if'. – Agentlien

Odpowiedz

7

Nie idziesz:

#include <type_traits> 
#include <iostream> 
#include <vector> 

template<typename T> 
struct is_const_mem_fn { 
private: 
    template<typename U> 
    struct Tester { 
     static_assert(// will always fail 
      std::is_member_function_pointer<U>::value, 
      "Use member function pointers only!"); 

     // if you want to report false for types other than 
     // member function pointers you can just derive from 
     // std::false_type instead of asserting 
    }; 

    template<typename R, typename U, typename...Args> 
    struct Tester<R (U::*)(Args...)> : std::false_type {}; 

    template<typename R, typename U, typename...Args> 
    struct Tester<R (U::*)(Args...) const> : std::true_type {}; 

public: 
    static const bool value = 
     Tester<typename std::remove_cv<T>::type>::value; 
}; 

struct A { 
    int member(); 
    int member() const; 
}; 
typedef int (A::*PtrToMember)(); 
typedef int (A::*PtrToConstMember)() const; 

int main() 
{ 
    std::cout 
     << is_const_mem_fn<PtrToMember>::value 
     << is_const_mem_fn<const PtrToMember>::value 
     << is_const_mem_fn<PtrToConstMember>::value 
     << is_const_mem_fn<const volatile PtrToConstMember>::value 
     << is_const_mem_fn<decltype(&std::vector<int>::size)>::value; 
} 

wyjściowa: 00111

EDIT: Jest to przypadek rogu zapomniałem uwzględnić w pierwotnej odpowiedzi.

Cecha powyżej będą dusić na hipotetycznej funkcji składowej takiego:

struct A { 
    int member(int, ...) const; 
}; 

bo nie ma ważnego specjalizacja Tester, które mogą być generowane dla takiego podpisu. Aby to naprawić, dodaj następujące specjalizacje:

template<typename R, typename U, typename...Args> 
struct Tester<R (U::*)(Args..., ...)> : std::false_type {}; 

template<typename R, typename U, typename...Args> 
struct Tester<R (U::*)(Args..., ...) const> : std::true_type {}; 
+0

Działa prawidłowo z gcc. Dzięki! – Akon

+0

@Akon Nie ma za co. Sprawdź również zaktualizowaną odpowiedź. – jrok

+0

Jeszcze raz dziękuję za głębsze spojrzenie na moje pytanie. – Akon

2

Poniżej znajduje się prosty typ cecha adaptacją here że powinno to pozwolić.

template <typename T> 
struct is_const_mem_func : std::false_type { }; 

template <typename Ret, typename Class, typename... Args> 
struct is_const_mem_func<Ret (Class::*)(Args...) const> : std::true_type { }; 
+2

Obowiązuje dla 'PtrToMember',' const PtrToMember' oraz 'PtrToConstMember'. ** ALE ** źle dla 'const PtrToConstMember' – deepmax

+0

Właściwa droga. Dzięki! – Akon