4

Is it possible to override (C-style) casts in C++?

Suppose I have the code

double x = 42;
int k = (int)x;

Can I make the cast in the second line execute some code I wrote? Something like

// I don't know C++
// I have no idea if this has more syntax errors than words
operator (int)(double) {
    std::cout << "casting from double to int" << std::endl;
}

The reason I ask is because of the question "Is there any way to get gcc or clang to warn on explicit casts?" and my suggestion there.

Community
  • 1
  • 1
pmg
  • 106,608
  • 13
  • 126
  • 198
  • 1
    Maybe if it's a cast from your own class. – chris Apr 25 '12 at 16:56
  • 1
    I suppose it is for user-defined classes, but not for built-in types. Which one do you care about? –  Apr 25 '12 at 16:57
  • 2
    No, you cannot override any operators for built-in types. They are all predefined by the compiler. – Bo Persson Apr 25 '12 at 16:57
  • 1
    If it could work for you, you could make a small container class for your double and provide an `operator int()` cast for it. That's the closest I can see it coming. – chris Apr 25 '12 at 17:01
  • +1 simply for: "I have no idea if this has more syntax errors than words" – Michael Burr Apr 25 '12 at 19:01

4 Answers4

5

§ 12.3.1/1 "Type conversions of class objects can be specified by constructors and by conversion functions. These conversions are called user-defined conversions and are used for implicit type conversions (Clause 4), for initialization (8.5), and for explicit type conversions (5.4, 5.2.9)."

Yes, we can make conversions, but only if one or both sides is a user-defined type, so we can't make one for double to int.

struct demostruct {
    demostruct(int x) :data(x) {} //used for conversions from int to demostruct
    operator int() {return data;} //used for conversions from demostruct to int
    int data;
};

int main(int argc, char** argv) {
    demostruct ds = argc; //conversion from int to demostruct
    return ds; //conversion from demostruct to int
}

As Robᵩ pointed out, you can add the explicit keyword to either of those conversion functions, which requires the user to explicitly cast them with a (demostruct)argc or (int)ds like in your code, instead of having them implicitly convert. If you convert to and from the same type, it's usually best to have one or both as explicit, otherwise you might get compilation errors.

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
  • You're the only person to look at it from the `int`'s point of view :) – chris Apr 25 '12 at 17:02
  • @chris: His question didn't mention any type specifically outside of the samples, and `int` is my default type :P I probably would have used `int` even if he didn't. – Mooing Duck Apr 25 '12 at 17:04
  • I mean well sure you can make a `MyDouble` class, but you can also make a `MyInt` class with a double constructor. It's close enough to draw the comparison. – chris Apr 25 '12 at 17:06
  • @chris : "You're the only person to have included a [conversion constructor](http://stackoverflow.com/questions/1384007/conversion-constructor-vs-conversion-operator-precedence)." FTFY. – Robᵩ Apr 25 '12 at 18:30
4

Yes, but only for your own types. Look at this:

#include <iostream>
struct D {
  // "explicit" keyword requires C++11
  explicit operator int() { std::cout << __FUNCTION__ << "\n"; }
};

int main () {
  int i;
  D d;
  //i = d;
  i = (int)d;
}

So, you cannot create double::operator int(), but you could create MyDouble::operator int().

Robᵩ
  • 163,533
  • 20
  • 239
  • 308
3

You can’t overload operators for built-in types, but you can write a conversion operator for a user-defined type:

struct Double {
    double value;
    operator int() const {
        shenanigans();
        return value;
    }
};

Since your question arose from a need to find explicit casts in code, also be aware that C++ has explicit casting operators. These are not only clearer than C-style casts, but also eminently searchable:

static_cast<T>(x)      // Cast based on static type conversion.
dynamic_cast<T>(x)     // Cast based on runtime type information.
const_cast<T>(x)       // Add or remove const or volatile qualification.
reinterpret_cast<T>(x) // Cast between unrelated pointer and integral types.
Jon Purdy
  • 53,300
  • 8
  • 96
  • 166
  • Note that you should know when to use the explicit casts before using them. Specifically things like `const_cast`. – chris Apr 25 '12 at 17:05
  • @chris: Well, yes, but having to know what you’re doing is a good thing. With a C-style cast, it’s much easier to do something you didn’t intend. – Jon Purdy Apr 25 '12 at 17:08
  • definitely! Just better to be aware though. Usually things are `const` for a reason. – chris Apr 25 '12 at 17:09
  • @chris: Naturally. And since everything that can reasonably be `const` probably should be, `const_cast(x)` appropriately conveys “here be dragons”; `(T*)x` does not. – Jon Purdy Apr 25 '12 at 17:14
1

Conversions to other types are overloadable operators in C++ (some examples here), but this fact will not help you.

Stroustrup wanted the language to be extensible, but not mutable. Therefore, overloading an operator only extends the operations to new types, but you cannot redefine what happens with any old types.

"However, to avoid absurdities, it is (still) not allowed to provide new meanings for the built-in operators for built-in types. Thus, the language remains extensible but not mutable."

Jirka Hanika
  • 13,301
  • 3
  • 46
  • 75