###

# Serialization

## `smart_cast`

### Motivation

To cast from one type to another related type, C++ provides the following operators:

`static_cast<T *>(U *)
static_cast<T &>(U &)`
  - required if neither T nor U are polymorphic
  - permitted in other cases.
  - fails to detect erroneous casts of polymorphic pointers/references at runtime.
  - does not permit "cross casting"
  - inline function calls can be optimized away during compile time.

`dynamic_cast<T *>(U *)
dynamic_cast<T &>(U &)`
  - permitted if either T or U are polymorphic
  - prohibited in other cases.
  - throws exception on detecting erroneous casts of polymorphic pointers/references at runtime.
  - permits "cross casting"
  - cannot optimise inline virtual functions at compile time.

These rules can make it difficult to use casting with a function template argument. Consider the following example:

    #include <boost/serialization/smart_cast.hpp>

    struct top {
    };

    struct base1 : public top {
        bool is_storable() const {
            return true;
        }
        virtual ~base1();
    };

    struct base2 {
        virtual ~base2();
    };

    struct derived1 :
        public base1
    {
        derived1();
    };

    struct derived2 :
        public base1,
        public base2
    {
        derived2();
    };

    template<class T>
    bool is_storable(T &t){
        // what type of cast to use here?

        // this fails at compile time when T == base2
        // return static_cast<base1 &>(t).is_storable();

        // this fails at compile time when T == top
        // otherwise it works but cannot optimize inline function call
        // return dynamic_cast<base1 &>(t).is_storable();

        // this always works - and is guaranteed to generate the fastest code !
        return (boost::smart_cast_reference<base1 &>(t)).is_storable();
    }

    int main(){
        derived1 d1;
        top & t1 = d1;
        derived2 d2;
        base2 & b2 = d2;

        bool result;
        result = is_storable(d1);
        result = is_storable(d2);
        result = is_storable(b2);
        result = is_storable(b2);
        result = is_storable(t1);
        return 0;
    }

The serialization library includes a mix of classes which use both static polymorphism (CRTP) and dynamic polymorphism via virtual functions. `smart_cast` was written to address the more problematic manifestations of the situation exemplified above.

### Usage

The following syntax is supported:

    smart_cast<Target *, Source *>(Source * s);
    smart_cast<Target *>(Source * s);
    smart_cast<Target &, Source &>(Source & s);

Note that the above syntax doesn't include

    smart_cast<Target & >(Source & s)

but the same functionality is supported with the following special syntax

    smart_cast_reference<Target &>(Source & s)

### Requirements

`smart_cast` can be used only on compilers that support partial template specialization or on types for which the macro `BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(<type>)` has been applied.

© Copyright Robert Ramey 2002-2004. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)