Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting const-ness of nested type

Normally, if I need to detect whether a type is const I just use boost::is_const. However, I ran into trouble when trying to detect the const-ness of a nested type. Consider the following traits template, which is specialized for const types:

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

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

The problem is that boost::is_const doesn't seem to detect that traits<const T>::reference is a const type.

For example:

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 outputs: false false

Why doesn't it output false true?

like image 248
Channel72 Avatar asked Jan 13 '11 18:01

Channel72


3 Answers

Because the reference is not const, it's the type it's referencing that is const. Right, there are no const references. So imagine that the reference is a pointer, then the difference is easier to understand: int const* not const, int *const is const.

Use remove_reference to get the actual const type:

cout << boost::is_const<
            boost::remove_reference<int const&>::type>::value << '\n';
like image 170
Yakov Galka Avatar answered Sep 24 '22 15:09

Yakov Galka


Because references are not const. :)

You have a ref-to-const (consider a rough analog, int const*, where the pointee int has a const context, but the pointer itself does not). The standard mixes terminology here, but I avoid the term "const ref" which is highly misleading.

References are inherently immutable as they can only be initialised and then not re-bound, but that does not make them const.

You can remove the reference from the type with boost::remove_reference (as indicated in other answers).

like image 23
Lightness Races in Orbit Avatar answered Sep 22 '22 15:09

Lightness Races in Orbit


Well, have you noted that is_const<int const&>::value is likewise false? It is. Something like this should be among the first things you try in order to debug templates like this. Another thing you can make use of is a type printer:

template < typename T > struct print;

When you instantiate that you'll get whatever T is in the error output, with most implementations.

Try this to solve your current problem:

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

like image 35
Edward Strange Avatar answered Sep 20 '22 15:09

Edward Strange