2011-01-13 12 views
7

Normalnie, jeśli potrzebuję wykryć, czy typ to const, po prostu używam boost::is_const. Podczas próby wykrycia stałej typu zagnieżdżonego wpadłem jednak w kłopoty. Rozważmy następujące cechy szablonu, który specjalizuje się w const typów:Wykrywanie konstytutywności typu zagnieżdżonego

template <class T> 
struct traits 
{ 
    typedef T& reference; 
}; 

template <class T> 
struct traits<const T> 
{ 
    typedef T const& reference; 
}; 

Problemem jest to, że boost::is_const nie wydaje się, aby wykryć, że traits<const T>::reference jest rodzajem const.

Na przykład:

std::cout << std::boolalpha; 
std::cout << boost::is_const<traits<int>::reference>::value << " "; 
std::cout << boost::is_const<traits<const int>::reference>::value << std::endl; 

This wyjścia: false false

Dlaczego nie wyjście false true?

Odpowiedz

13

Ponieważ odwołanie nie jest const, jest to typ, którego odwołanie jest const. Racja, nie ma żadnych odniesień stałych. Wyobraźmy sobie, że odwołanie jest wskaźnikiem, wtedy różnica jest łatwiejsza do zrozumienia: int const* nie const, int *const jest const.

Zastosowanie remove_reference uzyskać rzeczywisty typ const:

cout << boost::is_const< 
      boost::remove_reference<int const&>::type>::value << '\n'; 
4

Well, czy zauważył, że is_const<int const&>::value również jest fałszywy? To jest. Coś takiego powinno być jedną z pierwszych rzeczy, które wypróbujesz, aby debugować takie szablony. Inną rzeczą, jaką możesz wykorzystać to drukarka typ:

template < typename T > struct print;

Podczas wystąpienia, że ​​dostaniesz cokolwiek T jest w wyjście błędów, w większości wdrożeń.

Spróbuj rozwiązać aktualny problem:

is_const< remove_reference< traits<int const>::reference >::type >::value

+1

s/is_cost/is_const / –

6

Ponieważ referencje nie są const. :)

Masz ref-const (rozważ przybliżony analog, int const*, gdzie pointped int ma kontekst const, ale sam wskaźnik nie). Standardowo miesza tu terminologię, ale unikam terminu "const ref", który jest bardzo mylący.

Referencje są z natury niezmienne, ponieważ można je inicjować, a nie ponownie je wiązać, ale to nie czyni ich const.

Możesz usunąć referencję z typu przy pomocy boost::remove_reference (jak wskazano w innych odpowiedziach).