2013-03-05 13 views
11

Come posso rilevare una funzione membro con o senza modificatore?Determinazione della costanza della funzione membro

Si consideri il codice

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

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

ho bisogno di qualcosa di simile:

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

Se non si conoscono i tipi di dati di cui si ha a che fare quando si scrive il codice? –

+1

non sono la costanza della funzione membro verificata in fase di compilazione? – zzk

+2

@EdHeal E se fosse un argomento modello? Allora non sai fino alla istanziazione. Immagina di volerlo usare in un 'enable_if'. – Agentlien

risposta

7

ci si va:

#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; 
} 

uscita: 00111

EDIT: C'è un caso d'angolo ho dimenticato di spiegare nella risposta originale.

Il tratto sopra sarà soffocare una funzione membro ipotetico simili:

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

perché non c'è specializzazione valida Tester che può essere generato per tale firma. Per risolvere il problema, aggiungi le seguenti specializzazioni:

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

Funziona bene con gcc. Grazie! – Akon

+0

@Akon, prego. Si prega di controllare anche la risposta aggiornata. – jrok

+0

Grazie ancora per l'analisi approfondita della mia domanda. – Akon

2

Qui di seguito è un tipo semplice tratto adattato da here che dovrebbe permettere questo.

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

Valido per 'PtrToMember',' const PtrToMember' e 'PtrToConstMember'. ** MA ** sbagliato per 'const PtrToConstMember' – deepmax

+0

Modo corretto. Grazie! – Akon

Problemi correlati