2013-04-08 13 views
14

Dlaczego std::remove_const nie konwertuje const T& na T&? To wprawdzie raczej wymyślony przykład pokazuje moje pytanie:std :: remove_const z odniesieniami do stałych

#include <type_traits> 

int main() 
{ 
    int a = 42; 
    std::remove_const<const int&>::type b(a); 

    // This assertion fails 
    static_assert(
     !std::is_same<decltype(b), const int&>::value, 
     "Why did remove_const not remove const?" 
    ); 

    return 0; 
} 

Powyższa sprawa jest banalnie łatwe do naprawienia, więc dla kontekście wyobrazić, co następuje:

#include <iostream> 

template <typename T> 
struct Selector 
{ 
    constexpr static const char* value = "default"; 
}; 

template <typename T> 
struct Selector<T&> 
{ 
    constexpr static const char* value = "reference"; 
}; 

template <typename T> 
struct Selector<const T&> 
{ 
    constexpr static const char* value = "constref"; 
}; 

int main() 
{ 
    std::cout 
     << Selector<typename std::remove_const<const int&>::type>::value 
     << std::endl; 

    return 0; 
} 

W powyższym przykładzie, będę oczekiwać reference do wyświetlenia, a nie constref.

+0

Pamiętaj, że nie ma czegoś takiego jak odwołanie do const, a jedynie odwołanie do const. – xaxxon

Odpowiedz

13

std::remove_const usuwa najwyższego poziomuconst -. W dokumencie const T&, który jest równoważny z T const&, kwalifikacja nie jest najwyższym poziomem: w rzeczywistości nie ma zastosowania do samego odniesienia (które byłoby bez znaczenia, ponieważ odwołania są niezmienne z definicji), ale do typu odniesienia.

Tabela 52 w ustępie 20.9.7.1 z C++ 11 Określono, w odniesieniu std::remove_const:

typu element typedef wyznacza tego samego typu co T wyjątkiem tego każdej najwyższego poziomu const -kwalifikator został usunięty. [Przykład: remove_const<const volatile int>::type ocenia się volatile int, natomiast remove_const<const int*>::type ocenia do const int*. - przykładem koniec]

Aby rozebrać const daleko, trzeba najpierw zastosować std::remove_reference, następnie zastosować std::remove_const, a następnie (w razie potrzeby) stosuje std::add_lvalue_reference (lub to, co jest właściwe w danym przypadku).

UWAGA: W Xeo wspomina w komentarzu, można rozważyć using an alias template such as Unqualified wykonać dwa pierwsze etapy, tj znieść odniesienia, a następnie znieść ten const - (i volatile-) kwalifikacje.

+1

Pierwsze dwa są często zgrupowane razem pod aliasem 'Unqualified '. – Xeo

+0

@Xeo: Edytowane, dziękuję. –

+0

Ah, teraz rozumiem. Wielkie dzięki za wyjaśnienie. :) – dafrito

Powiązane problemy