开发者

Stopping an implicit cast on operator delete

开发者 https://www.devze.com 2022-12-17 08:48 出处:网络
My String class provides an operator char* overload to allow you to pass the string to C functions. Unfortunately a colleague of mine just inadvertently discovered a bug.

My String class provides an operator char* overload to allow you to pass the string to C functions.

Unfortunately a colleague of mine just inadvertently discovered a bug.

He effectively had the following code.

StringT str;
// Some code.
delete str;

Is there anyway to prevent delete from casting the string object to a char* to prevent future bugs like this cropping up? std::string gets round this problem by not providing a char operator overload but, ideally, I'd like to keep the overload but prevent that delete fr开发者_如何学Pythonom working.


Yes. Provide TWO implicit casts, by declaring (but not defining!) operator char const volatile*. When you're passing your StringT to a C string function, overload resolution will still select your original operator char const* (exact match). But delete str; now becomes ambiguous.

The declaration can be private, so if it would somehow be selected will be a compile-time error. The intended ambiguity occurs before overload resolution - the private only serves to catch the exceedingly rare cases where the volatile overload would be selected somehow.


Is there anyway to prevent delete from casting the string object to a char* ...?

Yep: Shy away from implicit casting operators. That's been preached for at least a decade now. Believe in it and you will lead a happier life.


Believe it or not, there is a reason std::string doesn't provide an implicit conversion, the c_str() function wasn't created just to irritate you. Provide implicit conversions and you open yourself up to a world of ambiguity and pain.


Controversial opinion time: If someone writes code that suffers from this "bug," they deserve to get bitten.

To paraphrase your question:

How do I keep people from using my firearms to shoot themselves in the foot?

You can't. I'll disagree with @sbi's opinion and say that your overload is fine. If this causes problems in someone's code, it's because someone doesn't know C++ and shouldn't be coding it.

You have bigger problems to worry about than whether or not someone who doesn't understand the language well enough to know not to delete things that aren't pointers can abuse your class.

Caveat: I am relatively new to C++, and have not seen the horrors of some more grizzled veterans. It is possible that a sample of particularly bad ambiguity might convince me of my evil ways. This, however, is not it.


struct Dummy {};
class StringT {
public:
    // ........
    operator char*() { /*...*/ }
    operator const char*() const { /*...*/ }

    operator const Dummy* () const { return 0; }
    operator Dummy* () { return 0; }
};

/// ...
void g(const char * ) { /*...*/ }

int main() {

    StringT str;
    g(str); // OK
    delete str; //error C2440: 'delete' : cannot convert from 'StringT' to 'void *'
    return 0;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号