Anycorn
Anycorn

Reputation: 51505

C++ restrict implicit construct to specific value

Suppose:

struct P {
    P(int v);
};

int v;
P p = 0; // allow
P q = v; // Fail at compile time

How can achieve that? any template trick?

I am trying to write allocator which has special pointer properties. unfortunately std implementation uses implicit conversion from int to NULL pointer:

{ return __n != 0 ? _M_impl.allocate(__n) : 0; }

my pointer implementation: http://code.google.com/p/asadchev/source/browse/trunk/projects/boost/cuda/mapped_ptr.hpp

my allocator implementation: http://code.google.com/p/asadchev/source/browse/trunk/projects/boost/cuda/allocator.hpp

I want to enforce explicit construction using raw pointer to avoid nasty problems.

Upvotes: 1

Views: 200

Answers (6)

Albert
Albert

Reputation: 68240

What about:

struct P {
    P(int v) { assert(v == 0); }
};

Some compilers might even see it already at compile time if you wrongly use this.

Upvotes: 0

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 507105

You can do it but you won't like it

struct P {
private:
    struct null_absorb;

public:
    P(null_absorb *v);
};

int v;
P p = 0; // allow
P q = v; // Fail at compile time

This will only allow null pointer constants. In other words, zero compile time values.

Upvotes: 6

Michael Kristofik
Michael Kristofik

Reputation: 35188

Do you really want to allow implicit conversions from int? That could open up a host of unintended coding errors. Since it's really a coding error to pass anything other than 0, you could do one of these:

#include <cassert>
struct P
{
    // Option #1, only allow 0 as an argument.
    explicit P(int v)
    {
        assert(v == 0);
        // other stuff goes here.
    }

    // Option #2, provide a no-argument constructor.
    P()
    {
        // behave like P(0)
    }
};

Upvotes: 2

user318904
user318904

Reputation: 3076

C++ 's static assert might do the trick: http://www.skynet.ie/~caolan/Fragments/C++StaticAssert.html

I think it is from newer C++ however.

Also, what about just initializing it to zero at compile time. Maybe making it constant.

Upvotes: 0

Reinderien
Reinderien

Reputation: 15263

I don't think there's any direct way to distinguish between a literal and a variable like you want. One alternative is to require the constructor to accept a reference to an integer: This would work with a variable, but not with a literal.

Upvotes: 1

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272657

I don't know why you'd want to do it, but something like:

struct P
{
protected:
    P(int v) {}

public:
    template <int N>
    static P create() { return P(N); }

};

int main()
{
    P p = P::create<0>();
}

Upvotes: 3

Related Questions