2013-03-05 11 views
11

Wie kann ich eine Elementfunktion erkennen const Modifizierer oder nicht?Konstanz der Elementfunktion finden

Betrachten Sie den Code

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

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

ich so etwas wie dieses brauchen:

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

Sollten Sie nicht wissen, die Datentypen, die Sie beschäftigen sich mit, wenn Sie den Code schreiben? –

+1

sind nicht constness der Member-Funktion zur Kompilierzeit überprüft? – zzk

+2

@EdHeal Was ist, wenn es ein Template-Argument ist? Dann weißt du es erst bei der Instantiierung. Stellen Sie sich vor, Sie möchten es in einem 'enable_if' verwenden. – Agentlien

Antwort

7

Dort gehen Sie:

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

Ausgang: 00111

EDIT: Es gibt eine Ecke Fall, dass ich in der ursprünglichen Antwort Konto vergessen zu.

das Merkmal oben wird Drossel auf einer hypothetischen Elementfunktion wie folgt aus:

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

da keine gültige Spezialisierung von Tester ist, die für eine solche Signatur erzeugt werden kann. Um es zu beheben, fügen Sie die folgenden Schwerpunkte:

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

Funktioniert gut mit gcc. Vielen Dank! – Akon

+0

@Akon Gern geschehen. Bitte überprüfen Sie auch die aktualisierte Antwort. – jrok

+0

Nochmals vielen Dank für den tiefen Blick auf meine Frage. – Akon

2

Im Folgenden ist eine einfache Art von Merkmal here angepasst, dass dies ermöglichen soll.

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

Gültig für 'PtrToMember',' const PtrToMember' und 'PtrToConstMember'. ** ABER ** falsch für 'const PtrToConstMember' – deepmax

+0

Richtiger Weg. Vielen Dank! – Akon