##all c++ explicit casts #std::move

  • — implicit casts
  • cvctor — is the most important implicit cast
  • conversion operator member-functions
  • numerical type conversions specified by C standard
  • — C:
  • parentheses cast
  • — C++03 added four casts
  • dynamic_cast — usable on references and pointers.
  • const_cast
  • reinterpret_cast — usually on pointers
  • static_cast
  • — c++11
  • std::move() — only for references, not pointers
  • std::forward()
  • numerous type conversions in type_traits.h
  • — boost:
  • boost::polymorphic_cast? is similar to dynamic_cast but much less popular and not essential knowledge expected of a c++ veteran

 

Advertisements

move() ^ pointer-casts: mostly compile-time

See https://stackoverflow.com/questions/27309604/do-constant-and-reinterpret-cast-happen-at-compile-time/27309763

  • dynamic_cast incurs runtime cost.
  • static_cast, const_cast, reinterpret_cast are compile-time
  • std::move() is compile time. An unconditional cast, according to Scott Meyers.

That’s for pointers or references.

Nonref variable cast is uncommon, unfamiliar and pretty much unnecessary, except for numeric types.  static_cast<std::string>("Hello") ends up calling std::string constructor.

static_cast^reinterpret_cast

I like the top answer in https://stackoverflow.com/questions/6855686/what-is-the-difference-between-static-cast-and-reinterpret-cast.

Both are unsafe casts and could hit runtime errors, but RC is more unsafe. RC turns off compiler error checking, so you are on your own in the dark forest.

I feel RC is the last resort, when you have control on the bit representation of raw data, with documented assurance this bit representation won’t change.

In a real example in RTS — a raw byte array comes in as a char array, and you RC it into (pointer to) a packed struct. The compiler has no reason to believe the char array can be interpreted as that struct, so it skips all safety checks. If the raw data somehow changes you get a undefined behavior at run time. In this case SC is illegal — will not pass compiler.

 

reinterpret_cast{int}( somePtr): practical use

http://stackoverflow.com/questions/17880960/what-does-it-mean-to-reinterpret-cast-a-pointer-as-long shows a real use case of reinterpret_cast from pointer to integer, and reinterpret_cast back to pointer.

What if I serialize an object to xml and the object contains a pointer field (reference field is less common but possible)? Boost::serialization would unwrap the pointer and serialize the pointee object.

Most of the time (like parsing unsigned char array), we reinterpret_cast from an (array) address into address of another data type

[[safeC++]] discourages implicit conversion via OOC/cvctor

See other posts about OOC and cvctor. I am now convinced by [[safeC++]] that it’s better to avoid both. Instead, Use AsXXX() method if converting from YYY to XXX is needed. Reason is type safety. In an assignment (including function input/output), it is slightly hacky if LHS is NOT a base type of RHS. Implicit conversion is like Subversion of compiler’s type enforcement — Given a function declared as f(XXX), it should ideally be illegal to pass in a YYY. However, The implicit converters break the clean rule, from the back door.

As explained concisely on P8 [[safeC++]], The OOC is provided specifically to support implicit conversion. In comparison, The cvctor is more likely to be a careless mistake if without “explicit”.

Favor explicit conversion rather than implicit conversion. Some manager in Millennium pointed out that c++ syntax has too many back doors and is too “implicit”. Reading a piece of code you don’t know what it does, unless you have lots of experience/knowledge about all the “back-doors”.

y dynamic_cast returns NULL on pointers

https://bintanvictor.wordpress.com/2010/01/14/new-and-dynamic_cast-exceptions-quick-guide/ shows that dynamic_cast of a pointer returns NULL upon failure. Why not throw exception?

A: for efficient test-down-cast. dynamic_cast is the only solution. If it throws exception, the test would have to incur the cost of try/catch.

See P59 [[beyond c++ standard lib]]

10 implicit translations by c++ compiler

See also posts on the “same” topic.

Note many inefficient implicit conversions are selectively, optionally “optimized away” by various compiler options. This adds even more complexity.

# proxy classes (like in [[more effC++]]) rely heavily on implicit translations
# smart pointer are drop-in replacement for raw pointers, and always relies on implicit compiler translations.
# “–any literal string–” anywhere in source code is implicitly converted to a char*const
# unnamed temporary object creation by compiler. [[more eff c++]]
# RVO
# [[c++ primer]] here are 3 identical func declarations because all array params are implicitly converted to ptr param. This is still very relevant because arrays are far more widely used than vectors (C is widespread) —
  void f(int * )
  void f(int[] )
  void f(int[5] )

#51 [[effC++]] Item 19 points out that if your Rational class overloads operator* with a Rational argument, then “aRational * 2” still works because compiler converts it first into
  aRational.operator*(2); // then it needs to convert 2 to a Rational object, so it converts the call into

  const Rational temp(2);
  aRational.operator*(temp);

#50) if f() declares a param of type Animal, you can pass in a Shape variable, if there’s a converter. (See effC++ Item 26). Applies to any LHS=RHS expression like

** Type5 var2 = var3ofUnrelatedType // you get either a Type5 conversion ctor or a conversion method in UnrelatedType, 

#10) overloading the arrow operator ie “->”. See P19/23 [[boost]]. IBM explains — The statement x->f() is interpreted as (x.operator->())->f()

smart pointer casts – using shared_ptr for illustration

Smart pointers are the infrastructure of infrastructures for a quant library.

Minor performance issues become performance critical in this foundation component. One example is the allocation of the reference count. Another example is the concurrent update of the reference count. But here my focus is yet another performance issue — the lowly pointer-cast. (I don’t remember why performance is a problem … but I believe it is.)

C++ support 4 specific casts but smart pointers need to -efficiently- implement const_cast and dynamic_cast, in addition to the implicit upcast.

Q1: why can’t I assign a smartPtr-of-int instance to a variable declared as smartPtr of Dog?
A: compiler remembers the type of each pointer variable.

Q2: in that case, should c++ compiler allow me to assign a SP-of-Derived instance to a variable declared as SP of Base?
%%A: I don’t think so. I don’t think every smart pointer automatically supports upcast, but boost shared_ptr does, by design. See below.

For Boost, a Barcap expert said there’s an implicit cast from shared_ptr of T (RHS) to (LHS) shared_ptr of const T. See the special casting methods in http://www.boost.org/doc/libs/1_48_0/libs/smart_ptr/shared_ptr.htm

Specifically, boost says shared_ptr can be implicitly converted to shared_ptr whenever T* can be implicitly converted to U*. This mimics the behavior of raw pointers. In particular, shared_ptr is implicitly convertible to shared_ptr (i.e. add constness), to shared_ptr where U is an public/protected base of T (i.e. upcast), and to shared_ptr.I believe this is the same “member template” magic in the smart pointer chapter of [[more effC++]]

Allow me to explain the basics — in basic C++, a raw-ptr-to-T instance can be assigned to these variables —
T const *  my_ptr_to_const_T;
U * my_ptr_to_a_T_parent_class_U;
void * my_ptr_to_void;

Therefore a raw ptr supports these 3 (among others) casts implicitly. So does shared_ptr.

clever use of enum(char?) in demanding c++ app #Miami

class Der: public Base {…..}

Requirement — we need to down cast a Base pointer. dynamic_cast has overhead.

Der* returnVal = static_cast (new Base) // will compile but is potentially disastrous, because the returnVal can be a partially wild pointer.

Q: without incurring the overhead of vtbl lookup, how do I decide if a pointer to Base given to me actually points to a Base or Der instance?

%%A: type_info still uses vtbl.
%%A: use a Base field to indicate the type. Both ctor will set the field, so the Der ctor will overwrite.
A: enum. If sizeof(aBase) is a tiny 2 bytes, then adding an enum field adds just 1 byte. Adding vptr would add 8 bytes. Big difference if we instantiate billions of this class.

You can also use a char, which is always 1 byte. An enum can be configured to take 1 byte, and have meaningful longer itemized names.

https://github.com/tiger40490/repo1/blob/cpp1/cpp/88miscLang/enumBasedRTTI.cpp has my tested code

user-defined implicit type conversion – uptake in C#

Q: in real c# applications, do folks really create user-defined conversion in their own classes? Is this a rarely “used” feature like java vararg, java nested interfaces, java annotations, java dynamic proxy..? By “rarely used” i mean java developers seldom _create_ such features in their classes, though they may use these features in “off-the-shelf” libraries.

A c# veteran answered — “It would likely be used primarily if you are creating an app framework ((library? not the same thing)), which occurs quite often still in each application silo .. We have a framework ((wrapping)) around Sql Server Analysis Services with Silverlight UI.  There are calculation engines which deal with Matrices and Vectors of data, so these types of structures would include some type conversion for the people using the framework.”

((everything in double paranthses are my annotations))

dissect`parametrized functor declaration-cum-construction

typedef void (*WorkerFunPtr)(const std::string&);

template<typename FunT,   // The type of the function being called
         typename ParamT> // The type of its parameter

struct Adapter {
   Adapter(FunT f, ParamT& p) : // Construct this adapter and set the
      f_(f), p_(&p) {}          // members to the function and its arg

   void operator( )( ) { // This just calls the function with its arg
      f_(*p_);        
   }
private:
   FunT    f_;
   ParamT* p_;  // Use the parameter’s address to avoid extra copying
};
void worker(const std::string& s) {} // a free function
int main( ) {
   boost::thread thr1(Adapter(worker, someStrVar)); // this line should be decomposed as
 
   Adapter // specialized type
        myAdapter(worker, someStrVar); // constructor

   boost::thread thr1(myAdapter);

Specializing a class template and then constructing an object is always a confusing process. Unfortunately we often have to do it in one line.
* specializing the Adapter template is simple enough, if we treat WorkerFunPtr as a simple type rather than a complicated typedef.
* constructing an object is simple enough
* However, the constructor is parametrized (since it’s in a class template), therefore the arguments have to match the actual types specified in the template specialization.
** worker is a function but implicitly converted to a function pointer. Its type does match the actual type WorkerFunPtr
** someStrVar does match the actual type std::string
==) Therefore this line constructs an object of the specialized type, using the 2 arguments — a func ptr and a string

Last lines passes the newly constructed myAdapter OBJECT to the thread constructor. Implicitly converted to qq/myAdapter.operator()()/ i.e. a no-arg function.
 

operator-overload ^ functions – incomplete summary

(IV? no)

Warning: some of the most important features/operations in c++ are implemented as special customizable operators like new/delete, qq(<<), call operator, OOC…, and their rules are sometimes unique, unusual and "bucking the trend". These help make OOL a rather confusing aspect of c++.

OOL has similar variations as function can have —

– free-standing OOL? Yes often as a friend function.
**Exception — call operator must be a method though I’m not sure about static methods
**Exception — I believe OOC must be a instance method.
– non-static non-virtual OOL? I think so. operators like ++ needs an instance.
– private non-static OOL? I think so
– (pure) virtual OOL? Probably not
– overloaded OOL? Yes esp assignment operator. I think qq/operator+/ too

Here’s a major difference between OOL vs functions –

– Regular Functions have a return type, possibly void. In contrast, some OOL must return a type and some OOL must not. See other blog posts.

vptr is a const non-static field – (slicing, casting)

When you “cast” a c++ or java POINTER[1] up and down family tree, the vptr field of the pointee persistently points to the “most derived” vtbl. To fully appreciate the constness of the vptr, consider slicing —

Q: during slicing, how does vptr end up pointing to the base vtbl?
A: copy constructor of the base object will be used, which (blindly) initializes vptr with the base object’s vtbl.

Background — vtbl is an array of func pointers. One vtbl per CLASS, but —

Q: Is there any compiler where superclass’s and subclass’s vtbl share the same address?
A: Won’t work. When slicing, the trim-down object’s vptr must NOT point to original vtbl. Trim-down object can never access derived class methods.
A: but what if a subclass overrides no method? Probably will share the vtbl with super class?

vptr is like a non-static const field. In the non-slicing scenario, The magic of polymorphism depends on the “vptr still pointing to subclass vtbl even if object is accessed by a base ptr”.

A twist on the constness — After this->vptr is initialized in the base ctor, it gets reseated during subclass ctor. During destruction, this->vptr gets reseated during Base dtor. This knowledge is relevant only if base ctor/dtor calls virtual methods.

[1] nonref won’t work.

q[new]+dynamic_cast exceptions quick guide

Seldom asked in IV, but …

Tip — dynamic_cast and new() used to behave similarly, but nowadays new() fails differently by default.

Q0: Both new and dynamic_cast normally returns a …. Yes a …. p o i n t e r

Q1: Failed dynamic_cast<someType &> returns ….
Q2: Failed dynamic_cast<someType * > returns ….
Q3: Failed boost polymorphic_cast returns ….
Q5: Failed “new” returns … in the past?
Q6: Failed “new” returns … nowadays?
Q6b: how do you change that behavior?

A1: never returns! Bomb out with std::bad_cast. Reference can’t be null in c++.
A2: 0 ie null ptr
A3: same as A1 — consistent for both ref and ptr
A5: 0 ie null ptr
A6: never returns! Bomb out with std::bad_alloc
A6b: new (nothrow) …

implicit interactions – casts && converters FROM nonref

Most casts operate on ref/ptr without creating objects[2], but most conversions happen on objects and nonref variables.Casting between unrelated ptr (or ref), where dynamic_cast and const_cast are irrelevant, is complicated and rare.

In this post, we focus on converting/casting FROM a nonref, either to a nonref or a pointer. dynamic_cast becomes irrelevant. Our tools are 1)static_cast 2)C-style cast, 3)implicit cast 4)explicit cvctor, 5)explicit OOC.

Conversions are notoriously implicit. One improvement is static_cast, which (still implicitly) invokes the conversion operations. Suppose we convert an object of Class S to an object of Class T. Either T has a cvctor (conversion ctor) or S has a OOC. I found some relevant coverage in the ARM —
static_cast can call OOC? yes
static_cast can call cvctor? yes. Also see http://www.cplusplus.com/doc/tutorial/typecasting/
static_cast can also call copy ctor – P70 effC++

assignment can call OOC? yes
assignment can call cvctor? probably yes to generate a temporary object

S s; T t;
t = s;

— nonref variable initialization by definition creates new objects
nonref variable initialization calls ooc? Y
nonref variable initialization calls cvctor? Y

pbclone implicitly calls ooc? Y
pbclone implicitly calls cvctor? Y

pbref calls ooc? illegal. won’t compile
pbref calls cvctor? illegal

Note in this more ugly cast expression, only OOC is usable:
MyClass::operator const char* () const{….}

[2] see post on casting-creating-new-pointer

decorating a c++ class to add converters

In java, i usually extend a bean class B to add data fields.

When using STL (P203 [[STL tutorial and ref]]), we often subclass a basic data class just to add conversion features. You can do the same using has-a decoration.

In STL, data classes need converters more often than in java. Java is more strict, more orthogonal — there’s often just one right way to do something. Perl, javascript and c++ data manipulation is more flexible. —————-}  Therefore more conversion is needed and implicit.

auto_ptr implementation notes – eSpeed IV

Someone asked me to implement a basic auto_ptr class template. It should be usable like

void foo(int * ip){…}

int* intP = new int(3);
AutoPtr aptr = ….. // create an AutoPtr object to encapsulate intP;
foo(someExpressionOfAptr);

Implement dtor, copier, op=… for the AutoPtr class,

Overload dereference, arrow to mimic pointer behavior.

Q: And what else?
A: cvctor to convert int ptr to an AutoPtr

Q: how about an operator-overload-converter (OOC) to convert from an AutoPtr to an int ptr? Why do we need it?
A: an auto ptr should be usable as an int ptr, ie foo(aptr). This requires the OOC.

Now you see the need to implicit convert both ways between AutoPtr and raw ptr!

c++ function names – 4-word, 3-word, 2-word

C++ function names are usually 1 word, i.e. 1 word before the “()”. There are exceptions, and all of them critical.

operator-overloads are special functions that always starts with “operator”. Trust me — “operator” is part of the function name. These are 2-word, 3-word function names. One of the longest is qq/ operator const char * () /

I don’t know if you can write

operator const vector ()

c++ exception handlers – global var

These “types” are aliases of the same type. Typedef over “ptr to void-void function”.

– terminate_handler / set_terminate() [1]
– unexpected_handler / set_unexpected() [1]
– new_handler / set_new_handler() [2]

Each setter modifies a global (implicitly static) variable. Global variable is quite common in C. The canonical global var is the errno global variable (which /bothers/ pthreads). I believe all of these global variables are shared by all threads.

For set_unexpected, Java offers similar things. (http://www.javapractices.com/topic/TopicAction.do?Id=229 highlights Swing EDT.)
* setUncaughtExceptionHandler()
* setDefaultUncaughtExceptionHandler()

[1] FAQ 271
[2] [[ effC++ ]]

c++ casts usually work with pointers and refences

dynamic_cast — target type must be ref or ptr
dynamic_cast — source must be ref or ptr
———
const_cast can operate on nonref, but usually operates on ptr and references. Specifically, const-ref is a common func param, and const_cast abounds here.
Q: const_cast — target/source type can be nonref?
A: less common. I believe LHS is a distinct object. See post on casting-creates-new-pointer. In this case const_cast is like a return-by-clone function.

See also post on const nonref
——–
static_cast is _less_ common, but …
Q: static_cast — target and source type can be nonref?
Q: static_cast — source can be nonref?
Q: static_cast — LHS can be nonref?
A: similar to const_cast.
A: yes effC++ says copy ctor may be invoked.
A: yes http://www.cplusplus.com/doc/tutorial/typecasting/

pointer-casting creates new pointer?

With some exceptions[1], c/c++ casts operate primarily on pointers (and references). That begs the question —
Q1: does pointer casting allocate 32 bits for a new pointer (assuming 32-bit addressing)?
A: depends on context

I feel the more basic question is

Q0: does pointer initialization allocate 32 bits for a new pointer?
A: i think so:

SomeType* p2 = p1; // allocates 32 bits for a new pointer p2, unless optimized away

Now back to our original Q1, i feel casting is like a function that returns an address in a specific “context” — address returned must be used as a Type3 pointer:

(Type3) p1;

In this case, if you don’t use this address to initialize another pointer, then system doesn’t allocate another pointer. but usually you put the cast on the RHS. The LHS therefore determines whether allocation is required

Type3* p3 = (Type3) p1; // 32-bit allocated
////////////////
Type3* p3=0; // this pointer could be on stack or heap
p3 = (Type3)p1; // no allocation since p3 already allocated.

As an extension of the LHS/RHS syntax, programmers also use function call syntax —

myFunction(123, (Type3)p1); // cast returns an address, to be saved in a temporary 32-bit pointer on the stack. This is more like pointer initialization.

[1] static_cast often operates on nonref variables, by implicitly invoking cvctor or OOC

up and down casting non-ref/ref/ptr

Primary usage of dynamic_cast is down-cast
* base/derived class must have vptr, or you get compile-time error
* original and target types must be ptr/ref, or you get compile-time error [1]
* there’s just one object involved, not 2
** That one object must be a complete and full[2] Derived object, otherwise you get runtime (not compile time) failure, indicated by 1) null ptr or 2) exception (during reference down-cast)
*** boost polymorphic_cast adds uniformity by throwing exception for both

[1] static_cast can cast nonref.
[2] static_cast doesn’t incur the overhead to check that

Q: up-casting a nonref??
A: no casting operator required, but you get sliced. qq/ myB = myD; /
A: by the way, no such thing in java, since java doesn’t use “nonref”

Q: down-casting a nonref??
A: impossible in dynamic_cast. “dynamic_cast can be used only with pointers and references to objects”

Q: down-casting a ptr (to a polymorphic object only)?
A: dynamic_cast. May return NULL. java has a similar feature.
A: see also boost polymophic_cast
Q: down-casting a ref (to a polymorphic object only)?
A: dynamic_cast. Never returns NULL. See post on new-and-dynamic_cast-exceptions
A: see also boost polymophic_cast

Q: down-cast a base ptr/ref to a derived object but no vtbl/vptr no virt func?
A: impossible. dynamic_cast won’t compile.

Q: up-cast a ptr?
A: common in c++ and java. everyday virtual function scenario. no operator required.

Q: up-cast a ref?
A: less common than ptr. See post on virtual^redefining

operator-overload return type — some examples

Summary — return type MUST be void in some cases, MUST be some specific type in some other cases, and can be up-to-you in other cases.

C++FAQ P297 points out that

A) overloaded operator often returns by reference to provide L-value semantics. Look at subscript operator and de-reference (the asterisk) a.k.a “unwrap” operators

B) In contrast, op-overload-converter (OOC) must have no return type since that’s redundant and confusing. Examples —

MyClass::operator const char*() const {…} // notice the double const. See full source code of String in [[nittyGrittyC++]]

operator string(); // P203 [[stl tutorial]]. You can also put your own class in there, like

operator myType();

—————– in contrast,
operator ()(){…} // can return bool or anything you like
operator= needs return type which is usually qq(return *this) by reference
operator+ must have return type since the result of addition or concat must be returned.

static_cast from nonref to ptr — idioms

MyClass e;

char* ptr2char = static_cast(e); // explicit

char* ptr2char2 = e; // implicit

char* ptr2char3 = (char*) e; //C-style explicit. After the bloomberg interview, I guess it’s legal but i would never do it

These mean the same. All invoke the qq/operator char*()/ ie the converter method in MyClass.

Q: How about a cvctor (convertor ctor)?
A: char* isn’t a class so can’t have a cvtor !!

dynamic_cast, typeid(*ptr) and vtbl

An interviewer pointed out if a pair of derived/base classes have no virtual function, then you can’t dynamic_cast between them even using pointers and references.

RTTI is inapplicable to types without vtbl, because such types are always fixed and known at compile time. For example D extends B, without any virtual method. We create a D object but give its address to a B pointer. What’s the typeid of the _unwrapped_ pointer? It’s a B. See post on AddressOfBasement.

#include
class base{
public: //virtual
    ~base(){}
};
struct derived: public base{};
int main(){
    base* p = new derived();
    cout<<typeid(*p).name(); // prints DERIVED if "virtual"; prints BASE otherwise 
    cin.get();
}

Also note
– a struct can extend a class, and vice versa
– dtor must be public to compile

conversion ctor ^ conversion method – pervasive

I feel the various type-converters are essential for code TRACING. Compiler implicitly uses conversion ctor (cvctor) and operator-overload-converter (OOC) whenever it needs to.

Note converter methods without “operator something” are explicitly invoked — much easier to spot. They often look like

   XXX asXXX(void)

As pointed out in other posts, cvctor and OOC can be invoked implicitly by static_cast into a nonref type.

Here are some converters —

Eg: scoped_lock myLock(myMutex);
Eg: string ( const char * s );
Eg: string.operator vector(), and string cvctor from vector. P197-198 [[STL tut]]
Eg: the conversions between auto_ptr, shared_ptr and raw ptr
Eg: conversion between vector iterators
Eg: back_inserter(myVector) returns a back_insert_iterator object