# include <boost/type_traits.hpp>
using boost::is_same;
using boost::is_pointer;
using boost::is_reference;
using boost::is_member_object_pointer;
using boost::add_const;
using boost::add_volatile;
using boost::add_cv;
using boost::add_pointer;
using boost::add_reference;
using boost::remove_const;
using boost::remove_volatile;
using boost::remove_cv;
using boost::remove_pointer;
using boost::remove_reference;
using boost::mpl::identity;
using boost::mpl::if_;

The improved const_cast_x<T> follows. Most of it is just copied from my earlier post. I have identified the changed parts in code comments, and I have taken out all the BOOST_MPL_ASSERT(..) and other explanatory and testing code in order to keep it brief. There are only two new template functions and two functions that have changed from the earlier version.

In closing, let me reiterate that it should be a goal to define const_cast<T> and the other primitive casting functions in C++. If the casts cannot be expressed as functions then we have found an expressive weakness in C++. And the functional definitions will give us an exact definition for these casts based on the C-style cast.

Yesterday I wrote about const_cast<T>(..) and how to define it in C++. But I did not make it work with data-member pointers because the Boost Type Traits library does not supply traits for data member objects. Here I’ll show you how to write type-traits and supporting template functions for data members. We’ll define the following templates:

member_object_pointer_traits<T>

add_member_object_pointer_const<T>

remove_member_object_pointer_const<T>

add_member_object_pointer_volatile<T>

remove_member_object_pointer_volatile<T>

add_member_object_pointer_cv<T>

remove_member_object_pointer_cv<T>

We’ll start with the headers.

# include <boost/type_traits.hpp>
using boost::is_same;
using boost::add_const;
using boost::add_volatile;
using boost::add_cv;
using boost::remove_const;
using boost::remove_volatile;
using boost::remove_cv;
using boost::remove_pointer;
# include <boost/mpl/assert.hpp>
// BOOST_MPL_ASSERT(..)
// BOOST_MPL_ASSERT_NOT(..)

We’d also like to be able to manipulate member-object pointers using functions like these:

add_const<T>

remove_const<T>

add_volatile<T>

remove_volatile<T>

add_cv<T>

remove_cv<T>

add_pointer<T>

remove_pointer<T>

But remove_pointer<T> cannot remove the pointer from member-object pointer types because the result is not a valid type. Also, add_const<T> and remove_const<T> cannot add/remove const that is buried in the member-object pointer.

And that’s how we can define template functions for working with member-object pointers in the Boost style. The traits for member-function pointers will resemble the function-traits class and will be more complicated.

We’ll use the templates we’ve defined here in the next post, when we extend our version of const_cast<T>(..) to work with member-object-pointers.

A few posts ago I wrote about cast_away_const(..), a function that removes the top-level const from a variable’s type. Unlike const_cast<T>(..), cast_away_const(..) can be called without specifying the return type as a template argument.

Of course const_cast<T>(..) is part of the C++ language and is provided by the compiler, so you don’t have to #include anything to get it. It’s not supposed to be a function and is not specified in functional terms. Until recently you couldn’t even simulate it as a function.

But that’s no longer true. The template language supported by modern compilers is a lot more sophisticated than it used to be, and you can now define your own const_cast<T>(..) to safely wrap a raw C-style casting. In this post I’ll show you how.

I’ll also argue that since const_cast<T>(..) can be defined as a function, it SHOULD be defined as a function. The implementation and test suite would then become the specification. C++ should be defined in C++ whenever possible.

# include <boost/type_traits.hpp>
using boost::is_same;
using boost::is_const;
using boost::is_volatile;
using boost::is_pointer;
using boost::is_reference;
using boost::add_cv;
using boost::add_pointer;
using boost::add_reference;
using boost::remove_cv;
using boost::remove_pointer;
using boost::remove_reference;
# include <boost/mpl/logical.hpp>
# include <boost/mpl/int.hpp>
using boost::mpl::bool_;
using boost::mpl::true_;
using boost::mpl::false_;
using boost::mpl::and_;
using boost::mpl::or_;
using boost::mpl::not_;
# include <boost/mpl/assert.hpp>
// BOOST_MPL_ASSERT(..)
// BOOST_MPL_ASSERT_NOT(..)

Let’s start with something simpler, has_const_somewhere<T>, which will give you an idea of how to implement const_cast<T>(..). In the following implementation, has_const_somewhere<T> starts with a type that looks something like int***&, and it peels off the layers, first removing the outer reference and then stripping off the pointers one by one, all the while looking for const. We’ll need something like that for const_cast<T>(..).

We’ll define strip_out_cv<T> in a similar way. strip_out_cv<T> removes all the const and volatile markers from a type of the form T*****& by peeling back all the layers and then putting them back again, but without const and volatile. Remember that const_cast<T>(..) deals with volatile as well as const.

This proves that it’s possible to write a close approximation to const_cast<T>(..) using templates. But we cannot specify exactly what const_cast<T>(..) is supposed to do by writing it in C++ yet because const_cast_x<T>(..) is not exactly right.

First of all, const_cast<T>(..) can cast away const in a data-member pointer while const_cast_x<T>(..) cannot.

These fail because casting is not necessary, and because you are only supposed to const_cast<T>(..) pointers, refs, and data-member pointers. const_cast_x<T>(..) could be fixed to work correctly here.

Or consider the following. All of these compile on msvc++9.0, but they all fail on g++3.4.5 (except for rpa6 and rppa6, which I cannot explain). Almost all of these work with both compilers if you use const_cast<..>(..) instead of const_cast_x<..>(..), although a few have r-value problems.

The r-value types coming in C++0x will let us refine and correct const_cast_x<..>(..)‘s behavior.

In conclusion, once we have r-values we will probably be able to define const_cast<T>(..) exactly as a C++ function, which should be something we strive for.

We should also have a way, maybe with static_assert(..) or #pragma, to improve compiler error and warning messages, such as those warning us of spurious casts or bindings to temporary values.

I also think it should be a goal to define the other casting forms as C++ functions. It’s almost possible now with reinterpret_cast<T>(..) and static_cast<T>(..). We’d need programmer access to the compiler-generated Run-Time Type Information (RTTI) to implement dynamic_cast<T>(..), so that should be a goal in a future version of C++. And of course polymorphic_cast<T>(..), polymorphic_downcast<T>(..), and numeric_cast<T>(..) are already defined as templated functions.