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