Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequential Type Casting of User Defined Type in C++

Tags:

c++

casting

This code compiles and runs with either a public implicit bool cast (commented out below, at http://ideone.com/FDJHB) or through a public implicit int cast followed by an implicit int to bool cast (as shown below, http://ideone.com/kHQ46). However, making the bool cast private (commented out below, at http://ideone.com/4poze) causes a compilation error. Why is the route through int no longer an option in that case? Do sequential casts like this have defined behavior? Thanks.

http://ideone.com/kHQ46

#include <iostream>

class MyObject {
 public:
  MyObject(int theInt) : theInt_(theInt) {
    return;
  }

  MyObject& operator=(MyObject& source) {
    std::cout << "assign op" << std::endl;
    theInt_ = source.theInt_;
    return *this;
  }

  friend MyObject operator*(MyObject& lhs, MyObject& rhs);

  operator int() {
    std::cout << "int conv" << std::endl;
    return theInt_;
  }

/*
  operator bool() {
    std::cout << "bool conv" << std::endl;
    return theInt_;
  }
*/

 private:

  int theInt_;

  MyObject(MyObject& source);
//  operator bool();

};

MyObject operator*(MyObject& lhs, MyObject& rhs) {
  std::cout << "mult op" << std::endl;
  return MyObject(lhs.theInt_*rhs.theInt_);
}


int main(int argc, char* argv[]) {

  MyObject a(1);
  MyObject b(2);
  MyObject c(3);

  if (a * b = c) std::cout << "Oh-no!" << std::endl;

  return 0;
}

EDIT: As requested, the relevant compiler messages.

1) Output for the code as given, cast to int to bool:

mult op

int conv

assign op

int conv

Oh-no!

2) Output for the code with public bool cast:

mult op

int conv

assign op

bool conv

Oh-no!

3) Compiler error if bool cast made private:

prog.cpp: In function ‘int main(int, char**)’:
prog.cpp:34: error: ‘MyObject::operator bool()’ is private
prog.cpp:50: error: within this context
like image 358
Praxeolitic Avatar asked Nov 17 '25 06:11

Praxeolitic


2 Answers

In order to convert your type to bool, the compiler selects the "best" conversion path according to a (fairly complicated) set of rules.

If operator bool() is defined, then that provides a better conversion than operator int() followed by a conversion from int to bool; a path with fewer conversions is regarded as "better".

Accessibility isn't taken into account in this process, so it will choose operator bool() even though it is private. Then compilation will fail, because operator bool() is private.

like image 82
Mike Seymour Avatar answered Nov 19 '25 21:11

Mike Seymour


In short, the compiler picks which method to call first, then checks to see if it's allowed to execute it. When it can see the operator bool that's the best match for an if check, so it picks that one and then discovers that it's private and can't be used.

Also note that (a * b = c) assigns c to the temporary returned from the multiplication and then evaluates whether that's zero or nonzero. I can't think of a scenario where such a thing would be useful.

like image 45
Mark B Avatar answered Nov 19 '25 22:11

Mark B