Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I overload an implicit initialization to 0?

Is it possible to write a class such that these are valid:

Foo a;
Foo b = 0;
Foo c = b;
Foo d(0);
Foo e(1);
Foo f = Foo(1);

But these are not:

int x;
Foo a = x;
Foo b = 1;
Foo c = 2;
//etc

Essentially, my rule is "A constant 0 is implicitly convertible to a Foo, but no other value is"

like image 482
Eric Avatar asked Jun 20 '13 14:06

Eric


Video Answer


1 Answers

If you don't mind Foo b = nullptr; working, it's pretty easy to hack up. Have an explicit constructor from int, and an implicit from std::nullptr_t.

If you do mind that working, I'm not sure it's possible. The only way to distinguish between a literal 0 and other integer literals is the former's implicit conversion to pointers and nullptr_t. So nullptr will prefer a nullptr_t parameter to a pointer parameter, so by having both constructors you could filter out nullptr arguments. However, the conversions of 0 to pointers and nullptr_t are of the same rank, so this would kill 0 arguments with an ambiguity.

Hmm ... something like this may work:

class Foo {
  struct dummy;
public:
  explicit Foo(int); // the version that allows Foo x(1);
  Foo(dummy*); // the version that allows Foo x = 0;
  template <typename T,
            typename = typename std::enable_if<
                std::is_same<T, std::nullptr_t>::value>::type>
  Foo(T) = delete; // the version that prevents Foo x = nullptr;
};

I haven't actually tried this. In theory, the template should only participate in overload resolution when the argument is nullptr, because otherwise SFINAE kills it. In that case, however, it should be better than the pointer constructor.

like image 57
Sebastian Redl Avatar answered Sep 28 '22 22:09

Sebastian Redl