16

What is implicit_cast? when should I prefer implicit_cast rather than static_cast?

Lundin
  • 195,001
  • 40
  • 254
  • 396
yesraaj
  • 46,370
  • 69
  • 194
  • 251
  • 6
    In case you are asking abt boost::implicit_cast; please edit the post to say so more clearly. – Abhay May 15 '09 at 13:00
  • @Abhay The concept of `implicit_cast` is a lot older than Boost - several years older. – curiousguy Dec 20 '11 at 21:35
  • 1
    @curiousguy: Things like an "implicit cast" don't exist, since a cast is always an explicit conversion request. Read the accepted answer for details... – Abhay Dec 21 '11 at 19:56
  • @Abhay The "implicit cast" idea really exist, since before the beginning of Boost. The `implicit_cast` template was proposed over and over again. It is natural, and the need for it is seen often. It should really be a standard cast, like `static`/`const`/`reinterpret_cast`. – curiousguy Dec 22 '11 at 14:20
  • 3
    @curiousguy: The idea did exist, but the question here was on the usage of 'implicit_cast' which does not exist in Std C++, hence a clarification was requested. – Abhay Dec 22 '11 at 15:37

4 Answers4

19

I'm copying over from a comment i made to answer this comment at another place.

You can down-cast with static_cast. Not so with implicit_cast. static_cast basically allows you to do any implicit conversion, and in addition the reverse of any implicit conversion (up to some limits. you can't downcast if there is a virtual base-class involved). But implicit_cast will only accept implicit conversions. no down-cast, no void*->T*, no U->T if T has only explicit constructors for U.

Note that it's important to note the difference between a cast and a conversion. In the following no cast is going on

int a = 3.4;

But an implicit conversion happens from double to int. Things like an "implicit cast" don't exist, since a cast is always an explicit conversion request. The name construct for boost::implicit_cast is a lovely combination of "cast using implicit conversions". Now the whole implementation of boost::implicit_cast is this (explained here):

template<typename T> struct identity { typedef T type; };
template<typename Dst> Dst implicit_cast(typename identity<Dst>::type t)
{ return t; }

The idea is to use a non-deduced context for the parameter t. That will avoid pitfalls like the following:

call_const_version(implicit_cast(this)); // oops, wrong!

What was desired is to write it out like this

call_const_version(implicit_cast<MyClass const*>(this)); // right!

The compiler can't deduce what type the template parameter Dst should name, because it first must know what identity<Dst> is, since it is part of the parameter used for deduction. But it in turn depends on the parameter Dst (identity could be explicitly specialized for some types). Now, we got a circular dependency, for which the Standard just says such a parameter is a non-deduced context, and an explicit template-argument must be provided.

Community
  • 1
  • 1
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
4

Prefer implcit_cast if it is enough in your situation. implicit_cast is less powerful and safer than static_cast.

For example, downcasting from a base pointer to a derived pointer is possible with static_cast but not with implicit_cast. The other way around is possible with both casts. Then, when casting from a base to a derived class, use implicit_cast, because it keeps you safe if you confuse both classes.

Also keep in mind that implicit_cast is often not needed. Using no cast at all works most of the time when implicit_cast does, that's where 'implicit' comes from. implicit_cast is only needed in special circumstances in which the type of an expression must be exactly controlled, to avoid an overload, for example.

Bruno Martinez
  • 2,850
  • 2
  • 39
  • 47
1

implicit_cast transforms one type to another, and can be extended by writing implicit cast functions, to cast from one type to another.

e.g.

int i = 100;
long l = i;

and

int i = 100;
long l = implicit_cast<long>(i);

are exactly the same code

however you can provide your own implicit casts for your own types, by overloading implicit_cast like the following

template <typename T>
inline T implicit_cast (typename mpl::identity<T>::type x) 
{
    return x;
}

See here boost/implicit_cast.hpp for more

Hope this helps

EDIT

This page also talks about implicit_cast New C++

Also, the primary function of static_cast is to perform an non changing or semantic transformation from one type to another. The type changes but the values remain identical e.g.

void *voidPtr = . . .
int* intPtr = static_cast<int*>(voidPtr);

I want to look at this void pointer, as if it was an int pointer, the pointer doesn't change, and under the covers voidPtr has exactly the same value as intPtr. An implicit_cast, the type changes but the values after the transformation can be differnet too.

Binary Worrier
  • 50,774
  • 20
  • 136
  • 184
  • 1
    "_the primary function of static_cast is to perform an non changing or semantic transformation from one type to another. The type changes but the values remain identical_" in this case (`static_cast`), the value doesn't change; in general, `static_cast` can change the type and the value: obvious example, `static_cast (3.14)` – curiousguy Dec 20 '11 at 21:42
1

Implicit conversions, explicit conversions and static_cast are all different things. however, if you can convert implicitly, you can convert explicitly, and if you can convert explicitly, you can cast statically. The same in the other direction is not true, however. There is a perfectly reasonable relationship between implicit casts and static casts. The former is a subset of the the latter.

See section 5.2.9.3 of the C++ Standard for details

Otherwise, an expression e can be explicitly converted to a type T using a static_cast of the form static_- cast(e) if the declaration T t(e); is well-formed, for some invented temporary variable t (8.5).

C++ encourages use of static_casts because it makes the conversion 'visible' in the program. Usage of casts itself indicates some programmer enforced rule which is worth a look so better use static_cast.

Abhay
  • 7,092
  • 3
  • 36
  • 50