Skip navigation

As a humorous-leaning answer to an unorthodox question, I invented the auto_cast utility. It looks abusive at first, but is it really so bad? It ended up making a small bit of noise on StackOverflow, so it may not be as bad as it looks.

Here is the final version for C++11:

#include <utility>

template <typename T>
class auto_cast_wrapper
{
public:
    template <typename R>
    friend auto_cast_wrapper<R> auto_cast(R&& x);

    template <typename U>
    operator U() const
    {
        // doesn't allow downcasts, otherwise acts like static_cast
        // see: http://stackoverflow.com/questions/5693432/making-auto-cast-safe
        return U{std::forward<T>(mX)};
    }

private:
    auto_cast_wrapper(T&& x) :
    mX(std::forward<T>(x))
    {}

    auto_cast_wrapper(const auto_cast_wrapper& other) :
    mX(std::forward<T>(other.mX))
    {}

    auto_cast_wrapper& operator=(const auto_cast_wrapper&) = delete;

    T&& mX;
};

template <typename R>
auto_cast_wrapper<R> auto_cast(R&& x)
{
  return auto_cast_wrapper<R>(std::forward<R>(x));
}

And an example:

#include <iostream>
#include <memory>

struct foo
{
    typedef std::unique_ptr<int> one_of_those_long_annoying_nested_types;
};

struct bar : foo
{
    bar(int&) { std::cout << "lvalue" << std::endl; }
    bar(int&&) { std::cout << "rvalue" << std::endl; }
};

foo::one_of_those_long_annoying_nested_types func()
{
    // fails, constructor marked explicit
    /* return new int; */

    // ugly solution, repeats return type
    /* return foo::one_of_those_long_annoying_nested_types(new int); */

    // nice solution, deduces cast and removes reptition
    return auto_cast(new int);
}

int main()
{
    // maintains value category
    int i = 0;
    bar b0 = auto_cast(i);
    bar b1 = auto_cast(std::move(i));

    // does not allow downcasts (use explicit static_cast for that!)
    foo f;

    foo& x = f;
    foo& y = b0;
    bar& z = b1;

    /* bar a = auto_cast(x); */
    /* bar b = auto_cast(y); */
    bar c = auto_cast(z);
}

At first it seemed a bit ugly and something to be avoided, but it does end up looking like a safer way to perform a static_cast, though one can invert the concept and do this instead:

T x = auto_cast(y); // becomes:
auto x = T{y};

Though you can’t perform that transformation in the context of return values, so auto_cast retains some usefulness.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>