2015-05-23 22 views
9

Jak uzyskać wartość boolean wskazującą, czy znana metoda ma kwalifikator const, czy nie?Jak sprawdzić, czy metoda jest stała?

Na przykład:

struct A { 
    void method() const {} 
}; 

struct B { 
    void method() {} 
}; 

bool testA = method_is_const<A::method>::value; // Should be true 
bool testB = method_is_const<B::method>::value; // Should be false 

W nagłówku type_traits znalazłem test is_const mogę używać, ale muszę rodzaj metody, i jestem pewien, w jaki sposób uzyskać to.

Próbowałem: std::is_const<decltype(&A::method)>::value ale to nie działa, i mogę zrozumieć, dlaczego (void (*ptr)() const) != const void (*ptr)()).

+1

na adres ostatnią część nie, to dlatego, że pierwsza jest wskaźnik funkcji stałej zwracający pustkę, a drugi wskaźnik funkcji zwracający unieważnienie. –

+0

Spekuluję także, że is_const przechwytuje typ zwracany, a nie kwalifikator const na samej funkcji. Nie mogę jednak poprawnie odpowiedzieć na to pytanie, ponieważ nie jestem pewien, jak sprawić, by zachowywał się tak, jak tego chcesz. –

+0

@William Dzięki za pomoc. Tak, nie wiem, jak sprawdzić to zakwalifikowanie const =/ –

Odpowiedz

7

O wiele łatwiej jest sprawdzić, czy funkcja członkowska może zostać wywołana na const - kwalifikowanej l-wartości.

template<class T> 
using const_lvalue_callable_foo_t = decltype(std::declval<const T&>().foo()); 

template<class T> 
using has_const_lvalue_callable_foo = std::experimental::is_detected<const_lvalue_callable_foo_t, T>; 

spłukać i powtórzyć, z wyjątkiem std::declval<const T>(), aby sprawdzić, czy wspomniana funkcja może być wywołana na const -qualified rvalue. Nie mogę wymyślić żadnych dobrych przypadków użycia dla funkcji składowych const &&, więc wątpliwe jest, czy istnieje możliwość wykrycia tego przypadku.

Skonsultuj się z bieżącym Library Fundamentals 2 TS working draft, jak wdrożyć is_detected.


Jest dużo bardziej zawiłe, by sprawdzić, czy dany wskaźnik do funkcji członków punkty typ do typu funkcji ze szczególnym cv-kwalifikatora nast. To wymaga 6 częściowych specjalizacji na cv-qualifier-seq (const i const volatile są różne cv-qualifier-seq s) i nadal nie może obsłużyć przeciążonych funkcji składowych lub szablonów funkcji członka. Szkicując pomysł:

template<class T> 
struct is_pointer_to_const_member_function : std::false_type {}; 

template<class R, class T, class... Args> 
struct is_pointer_to_const_member_function<R (T::*)(Args...) const> : std::true_type {}; 

template<class R, class T, class... Args> 
struct is_pointer_to_const_member_function<R (T::*)(Args...) const &> : std::true_type {}; 

template<class R, class T, class... Args> 
struct is_pointer_to_const_member_function<R (T::*)(Args...) const &&> : std::true_type {}; 

template<class R, class T, class... Args> 
struct is_pointer_to_const_member_function<R (T::*)(Args..., ...) const> : std::true_type {}; 

template<class R, class T, class... Args> 
struct is_pointer_to_const_member_function<R (T::*)(Args..., ...) const &> : std::true_type {}; 

template<class R, class T, class... Args> 
struct is_pointer_to_const_member_function<R (T::*)(Args..., ...) const &&> : std::true_type {}; 

Jeśli chcesz const volatile być true też zlikwidować kolejne 6 częściowych specjalizacji wzdłuż tych linii.

+0

Wybacz moją ignorancję, ale o czym jest ten odnośnik? Czy zawiera oficjalne rozszerzenia, które są już dostępne w standardzie C++ X, czy jest to propozycja dla przyszłej wersji? –

+1

@JanitoVaqueiroFerreiraFilho Jest to robocza wersja proponowanej specyfikacji technicznej.Rzeczy tam prawdopodobnie przejdą do następnej wersji standardu C++. Jeśli chodzi o 'is_detected', zostało ono poddane pod głosowanie dwa tygodnie temu, więc prawdopodobnie nie ma jeszcze dostępnej implementacji, ale TS zapewnia pełną jego implementację, więc możesz go po prostu wziąć i użyć. –

+0

Twoja implementacja ignoruje funkcje, które można wywoływać tylko na wartościach r, czyż nie? – Columbo

6

Przyczyna std::is_const<decltype(&A::method)>::value nie działa, ponieważ funkcja składowa stała nie jest stała (funkcja składowa). Nie jest to najwyższy poziom w stylu, który byłby dla const int vs int.

Co możemy zrobić, a nie jest to cecha typ używając void_t który sprawdza, czy możemy nazwać method na const T:

template <typename... > 
using void_t = void; 

template <typename T, typename = void> 
struct is_const_callable_method : std::false_type { }; 

template <typename T> 
struct is_const_callable_method<T, void_t< 
    decltype(std::declval<const T&>().method()) 
    > > : std::true_type { }; 

Demo

Powiązane problemy