Avoiding implicit conversion in constructor. The 'explicit' keyword doesn't help here
Solution 1:
You can delete
A::A(<anything not an int>);
:
struct A
{
explicit A(int a)
: num(a)
{}
template<class T>
A(T) = delete;
int num;
};
int main()
{
//A a1=A(10.0); // error: use of deleted function 'A::A(T) [with T = double]'
A a2 = A(10); // OK
(void) a2;
}
Demo: https://coliru.stacked-crooked.com/a/425afc19003697c9
Solution 2:
The way to achieve this is to provide another constructor that would be a better match, and then delete
it so you'll get an error. For your class, adding
template <typename T>
A(T) = delete;
Will stop the class from being constructed from anything that isn't an int
Solution 3:
You can circumvent this problem by using braced initialization. For example:
struct A {
A(int _a) : a(_a) {}
int a;
};
A a{5}; // ok
A b{1.123}; // compile error
Proof
Solution 4:
I just want to add that the A(double) = delete
is a C++11
addition.
If for whatever reason you cannot use this relatively new construct, you can simply declare it as private as this:
class A{
public:
A(int);
private:
A(double);
}
Solution 5:
To avoid int->double conversions everywhere, not only in your case. With g++ you can use -Wconversion -Werror
. Note that it'll be allowed in your particular case, because the compiler understands that 10.0 is literal, but it will fail compilation for:
class A
{
public:
explicit A(int a)
{
num = a;
}
int num;
};
int main()
{
double x = 10;
A a1 = A(x);
static_cast<void>(a1);
return 0;
}
Compiler explorer