Alex
Alex

Reputation: 876

Warning about using explicit keyword in a conversion operator

so I have a class named Date which looks like this:

class Date {
private:
    UINT month, day, year;
    std::string DateToString;
public:
    Date(UINT inMonth, UINT inDay, UINT inYear)
    : month(inMonth), day(inDay), year(inYear){}

    operator PCSTR() {
        //essentially just an ostream that takes strings inside it
        std::ostringstream formattedDate;
        //feed it and convert integers as well
        formattedDate << this->month << " / " << this->day << " / " << this->year;

        //get content of stream as a pointer with str() method
        //store the pointer in local var to avoid it to being invalidated after RET was hit and cout not able to display
        this->DateToString = formattedDate.str();
        return DateToString.c_str();//convert that ostringstream string to a PCSTR
    }
}

Note: I'm using Windows data types with PCSTR being a const char* and UINT an unsigned int.

Now this class serves as a date instantiation class: Date test(1, 10, 2020), I've created the operator PCSTR() member method to be able to use it in cout, because the latter will use the most suited operator conversion to be able to display an object, and here we use const char*/PCSTR because cout does not have any problems displaying them. So if I do cout << test; it displays 1/10/2020.

Now on my code editor it tells me 'operator const char *' must be marked explicit to avoid unintentional implicit conversions, I don't understand, isn't that what we want, if I mark it explicit then I must cast the object, why can't I just leave it like that? What other conversions can happen with const char*?

Thanks in advance.

Upvotes: 0

Views: 272

Answers (2)

Asteroids With Wings
Asteroids With Wings

Reputation: 17454

Now on my code editor it tells me 'operator const char *' must be marked explicit to avoid unintentional implicit conversions

That's right. This is just a warning, but it's a good one!

I don't understand, isn't that what we want

No!

if I mark it explicit then I must cast the object

That's a good thing. It avoids accidents.

why can't I just leave it like that?

You can if you want to. But I recommend that you don't.

Upvotes: 1

joshwilsonvu
joshwilsonvu

Reputation: 2679

I can think of one unintentional implicit conversion here. If you were to accidentally write

Date date;
// ...
if (date) { /* ... */ }

the compiler could first convert date to const char*, and then const char* to bool, and this would be a difficult-to-debug situation. The explicit operator protects against this situation.

There's a better way to define how your class should be printed to std::cout:

class Date {
  // ...
  std::string toString() const {
    // ...
    return formattedDate.str();
  }
}

std::ostream& operator<<(std::ostream& out, const Date& date) {
  return out << date.toString();
}

If you must use a conversion operator, why not make it explicit and convert where needed? It would be easier to see from the code exactly what is happening.

std::cout << static_cast<const char*>(date);

Upvotes: 4

Related Questions