You're confusing some concepts here.
explicit
prevents implicit constructor calls, not constructor calls with implicit parameter type conversions.
Unfortunately the solution is not straightforward. It's not quite newbie-friendly and may require some googling to understand.
You could expicitly delete the constructors for floating-point types: foo(float) = delete;
and so on. Then foo f(0.1);
will cause 'use of deleted function' error. But you won't be able to do foo f(1l)
either, the compiler will complain about 'ambiguous overloads'.
The proper way is following:
class foo
{
public:
foo(int) {std::cout << "int constructor\n";}
template <typename T,
typename = std::enable_if_t<std::is_floating_point_v<T>>>
foo(T) = delete;
};
It's similar to deleting overloads for each floating-point type (as described above), but due to SFINAE, the deleted overload won't be considered for non-floating-point types.