'Can casts be completely avoided with a good design?

I'm wondering whether situation exists where casting is completely necessary.
I'm talking here about casts between classes, not basic types.

Is casting (be it C++ style like static_cast or dynamic_cast, or plain C-style cast) a code smell? I can see how sometimes it's helpful, but I think it can also be avoided. Does casting break any OOP rules?



Solution 1:[1]

If by code smell you mean that it should raise a flag in a code review, then they are a code smell. If you mean that they should never appear in code, then no, there are some fine uses of casts.

For an interesting example (I always find type erasure interesting), take a look at the implementation of boost::any where dynamic_cast is required to safely read from the stored value (unlike unions where you must guess the type and are limited)

Sketch:

struct any_base {
   virtual ~any_base() {}
};
template <typename T>
struct any_data : any_base {
   T value;
   any_data( T const & value ) : value(value) {}
};
struct any {
   any_base * data;
   any() : data() {}
   ~any() { delete data; }

   template <typename T>
   any( T const & v ) : data( new any_data<T>(v) {}
}
template <typename T>
T any_cast( any const & a ) {
   any_base<T> * p = dynamic_cast< any_base<T>* >( a.data );
   if ( !p ) throw invalid_cast();
   return *p;
}

Solution 2:[2]

Not especially. Casts should be avoided whenever possible, but at the most fundamental level, there are regions of C++ that exist outside the realm of type safety, and casts are necessary. dynamic_cast is a special exception, specifically, it can be necessary even in a solid OOP design.

There are "that's imperfect" and there's "OMGWTF, Y U SO DUMB". Casts are just imperfect.

Solution 3:[3]

The typical example is I/O: This is one of the few and only reasons to cast, and it also uses one of the only legitimate pointer types in C++: char *:

uint32_t n;
infile.read(reinterpret_cast<char *>(&n), sizeof n);
n *= 2;
outfile.write(reinterpret_cast<const char *>)(&n), sizeof n);

Other "I/O-like" operations require a similar pattern, such as encryption or encoding conversion.

(The other legitimate pointer in C++ is void * when used in the context of allocation, but it shouldn't need to be cast: The C++ way to "convert" a memory pointer to an object pointer is via construction: void * addr = get_memory();, then T * p = new (addr) T;.)

Solution 4:[4]

I would say that casting cannot be completely avoided by good design because there are reasonable cases where casting is a good choice. Proxies are enormously useful and usually rely on implicit or explicit casting such as the following which does lazy evaluation.

template <class fn_t, class result_t>
class lazy_t {
    fn_t fn_;
public:

    lazy_t(fn_t fn) : fn_ (fn) { }

    operator result_t () { return fn_(); }
};

In this case the compiler can use implicit casting to perform lazy evaluation of a given function. I would consider the conversion operator a part of the public interface of the class.

dynamic_cast<> is also necessary in certain cases such as implementing multiple-dispatch. See http://en.wikipedia.org/wiki/Multiple_dispatch for more on this.

Sometimes your programs require complicated code. You can't always just stick to the simple, basic or "clean" elements of the language.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 David Rodríguez - dribeas
Solution 2 Puppy
Solution 3
Solution 4 Bowie Owens