8

I have a constructor of the form:

MyClass(int a, int b, int c);

and it gets called with code like this:

MyClass my_object(4.0, 3.14, 0.002);

I would like to prevent this automatic conversion from double to int, or at least get warnings at compile time.

It seems that the "explicit" keyword does not work in these case, right?

Hugo
  • 1,065
  • 1
  • 10
  • 11

3 Answers3

9

What's your compiler? Under gcc, you can use -Wconversion to warn you about these types of conversions.

Martin B
  • 23,670
  • 6
  • 53
  • 72
  • I use gcc, and the -Wconversion did work! I thought the -Wall would include this, but apparently it doesn't! Thanks a lot! – Hugo Feb 19 '10 at 09:06
  • 2
    -Wall lacks a lot of things and not even -Wall -Wextra includes everything. I would prefer having a switch to really enable all warnings and then disable the ones that are causing trouble one-by-one. – Tronic Feb 19 '10 at 09:17
  • 1
    Personally, I compile with '-Wall -Wextra -pedantic -Wformat=2 -Wstrict-overflow=3 -Werror'. I add '-Wno-unused' during development because I often have things that I'm not quite ready to use yet, but I want them in there because I know I'll need them. – David Stone Jan 20 '12 at 01:30
5

Declare a private constructor like this:

private:
template <class P1, class P2, class P3>
MyClass(P1,P2,P3);

That will cause a compile time error for any construction using 3 parameters that aren't all int, and it's portable.

JoeG
  • 12,994
  • 1
  • 38
  • 63
  • That's clever. :-) The warning solution is a bit cleaner, but your solution works on any conforming compiler. :-) Unfortunately it does not protect against the class constructing instances of itself directly. You have to wait until link time to catch those. – Omnifarious Feb 19 '10 at 09:25
  • @Omnifarious: With C++0x you'd simply mark this overload with `= delete;` Otherwise, if you were worried about internal misuse, you could provide an implementation that fails to compile (e.g because of static assertion). – visitor Feb 19 '10 at 11:43
  • Cleverer: add a second overload `template MyClass(P1,P2,P3, P3* dummy = 0);`. Overload resolution between the two templates will be ambiguous, but this is irrelevant if both are worse than `MyClass(int,int,int)` – MSalters Feb 19 '10 at 11:44
  • @visitor: I believe `= delete;` can only be used to remove functions that would otherwise be automatically declared and defined by the compiler. – Omnifarious Feb 19 '10 at 21:19
  • @Omnifarious: It seems eliminating unwanted conversions is one intended usage of `= delete`. See the C++0x FAQ: http://www2.research.att.com/~bs/C++0xFAQ.html#default – visitor Feb 22 '10 at 11:44
  • @visitor: How interesting. Reading the rationale behind their choice in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2326.html makes their choice seem very sensible. It was intended for exactly this sort of situation. Thanks! – Omnifarious Feb 22 '10 at 16:53
2

Declare a private MyClass(double a, double b, double c) constructor.

Kristopher Johnson
  • 81,409
  • 55
  • 245
  • 302