zwol
zwol

Reputation: 140569

Initialize instance with integer constant 0 but no other constant value or integer variable

I want to define a class whose instances can be constructed, implicitly constructed, or assigned from an integer constant zero, but not from any other numeric constant, and not from a variable with integer type (even if its value happens to be zero at runtime). It should also be copy-constructible from other instances of the same class. Use of C++11 features is okay as long as they're supported (in the appropriate mode) by both g++ 4.6 and MSVC 2010.

Concretely, given

class X { /* ... */ };
void fn(X);

these should all compile:

X a(0);
X b = 0;
X c; c = 0;
X d = a;
X e; e = a;
fn(0);

but these should not:

X f(1);
X g = 1;
X h; h = 1;
fn(1);

int ii = 23;
X a(ii);
X j = ii;
X k; k = ii;
fn(ii);

I tried this, but it didn't work:

class X {
public:
   X() {} 
   constexpr X(int v) { static_assert(v == 0, "must be initialized from zero"); }
};

test.cc: In constructor ‘constexpr X::X(int)’:
test.cc:3:29: error: non-constant condition for static assertion
test.cc:3:29: error: ‘v’ is not a constant expression

Upvotes: 6

Views: 361

Answers (3)

Philipp
Philipp

Reputation: 49802

You could make use of the fact that only 0 can be implicitly converted to a pointer:

struct X {
  X();
  X(void*);
};

This fulfills your requirements, but of course allows initialization with a pointer as well.

Upvotes: 0

user319799
user319799

Reputation:

If require C++0x, you could use std::nullptr_t:

class X
{
public:
  X () { }
  X (std::nullptr_t) { }
  void operator= (std::nullptr_t) { }
};

Well, with the downside that X becomes initializable with nullptr too, of course.

Upvotes: 2

clanmjc
clanmjc

Reputation: 299

You need to replace (v == 0) with a constant expression...

Something like

constexpr bool is_zero_construct(size_t number)
{
  return number == 0;
}

constexpr X(int v) { static_assert(is_zero_construct(v), "must be initialized from zero"); }

Upvotes: 1

Related Questions