Reputation: 140569
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
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
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
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