0

I have a class whose only data member is a 32 bit unsigned integer. That is, the class looks like this:

class A {
protected:
    unsigned int bits;
    /* ... some methods ... */
public:
    /* ... some methods ... */
};

But I want it to also be able to implicitly convert to and from 32 bit unsigned integers. So I added in a copy constructor as well as a casting operator:

class A {
protected:
    unsigned int bits;
    /* ... some methods ... */
public:
    A(): bits(0) {} // default constructor
    A(const unsigned int i): bits(i) {} // convert from unsigned int to A
    operator unsigned int() { return bits; } // convert from A to unsigned int
    /* ... some methods ... */
};

So now for example, I can do the following things:

int main () {
    // default constructor
    A a0 = A();
    // convert from unsigned int
    A a1 = 1 + 2;
    // conversions between the two types:
    unsigned int result = (a0 & a1 + 5) / 2;
}

However I'm struggling to get it to work with const types. In particular, the following doesn't work:

int main () {
    const A a = 5;      // works
    unsigned int i = a; // compiletime error
}

It says "No suitable conversion function from 'const A' to 'unsigned int' exists.". I'm using Visual Studio 2010 with the default compiler as provided by microsoft.

What conversion function do I need to create for it to work properly?

Cam
  • 14,930
  • 16
  • 77
  • 128
  • Re: "But I want it to also be able to implicitly convert to and from 32 bit unsigned integers." Be careful of what you ask for. Implicit conversions will bite you in the rear end when you least expect it, and experienced C++ programmers often avoid allowing implicit conversions in their classes except in only a few circumstances. What benefit do you think you'll get by allowing this kind of implicit conversion for class `A`? – In silico Apr 08 '12 at 03:48
  • @Insilico: Cleaner code, since I won't have to write casts everywhere when I'm performing operations on the bits. – Cam Apr 08 '12 at 03:49
  • And using public methods or operator overloading to implement those bit operations aren't adequate? – In silico Apr 08 '12 at 03:51
  • @Insilico: I want to be able to use all operations that could be performed on an unsigned int, so this seems like the easiest and most straightforward way to do things. Can you explain in more detail why it's a bad idea to proceed the way I am? – Cam Apr 08 '12 at 03:54
  • http://stackoverflow.com/questions/2346083/why-implicit-conversion-is-harmful-in-c That being said, I'm not saying you should avoid implicit conversion operators completely (they're not *that* dangerous), but I am saying you should be extra careful about it. – In silico Apr 08 '12 at 03:58
  • @Insilico: Makes sense. Thanks for helping out! I think I'm going to carry on with this, but I'll keep your advice in mind before going coercion crazy in the future :) – Cam Apr 08 '12 at 04:03

1 Answers1

3

Declare the conversion operator const:

operator unsigned int() const { return bits; }

Caveat: Implicit conversion operators are almost always a bad idea. The dangers usually far outweigh the minor inconvenience of calling a plain old member function:

unsigned int asInt() const { return bits; }
⋮
unsigned int i = a.asInt();

The ultimate solution, if you have C++11, is to declare an explicit conversion operator:

explicit operator unsigned int() const { return bits; }
⋮
unsigned int i = static_cast<int>(a);
Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
  • 1
    Thanks! Makes sense. I'll accept your answer after the time limit but can you go into more detail about why it's so dangerous? – Cam Apr 08 '12 at 03:52
  • Regarding the explicit conversion operator - very cool but if I do that, I have to `static_cast` everytime I use one of the unsigned int operators on an A object, which I'd rather not do. Can you go into more detail about the dangers of allowing such implicit conversions in this situation? – Cam Apr 08 '12 at 03:56
  • @Cam: It isn't *incredibly* dangerous, just plain vanilla dangerous, and the alternative is such a minor imposition that it usually isn't worth the risk. You should never trade safety for a small gain in convenience. – Marcelo Cantos Apr 08 '12 at 03:57