C ++ ограничивает неявную конструкцию конкретным значением - PullRequest
1 голос
/ 28 сентября 2010

Предположим:

struct P {
    P(int v);
};

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

Как этого добиться? любой шаблон трюк?

Я пытаюсь написать распределитель, который имеет специальные свойства указателя. к сожалению, реализация std использует неявное преобразование из int в NULL-указатель:

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

моя реализация указателя: http://code.google.com/p/asadchev/source/browse/trunk/projects/boost/cuda/mapped_ptr.hpp

моя реализация распределителя: http://code.google.com/p/asadchev/source/browse/trunk/projects/boost/cuda/allocator.hpp

Я хочу применить явную конструкцию, используя необработанный указатель, чтобы избежать неприятных проблем.

Ответы [ 6 ]

6 голосов
/ 28 сентября 2010

Вы можете сделать это, но вам это не понравится

struct P {
private:
    struct null_absorb;

public:
    P(null_absorb *v);
};

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

Это разрешит только константы нулевого указателя. Другими словами, нулевые значения времени компиляции.

3 голосов
/ 28 сентября 2010

Я не знаю, почему вы хотите это сделать, но что-то вроде:

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

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

};

int main()
{
    P p = P::create<0>();
}
2 голосов
/ 28 сентября 2010

Вы действительно хотите разрешить неявные преобразования из int?Это может открыть массу непреднамеренных ошибок кодирования.Так как это действительно ошибка кодирования для передачи чего-либо, кроме 0, вы можете сделать одно из следующих действий:

#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)
    }
};
1 голос
/ 28 сентября 2010

Я не думаю, что есть какой-либо прямой способ различать литерал и переменную так, как вы хотите. Одна альтернатива - требовать, чтобы конструктор принял ссылку на целое число: это будет работать с переменной, но не с литералом.

0 голосов
/ 28 сентября 2010

А как насчет:

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

Некоторые компиляторы могут даже увидеть его уже во время компиляции, если вы неправильно его используете.

0 голосов
/ 28 сентября 2010

Статическое утверждение C ++ может помочь: http://www.skynet.ie/~caolan/Fragments/C++StaticAssert.html

Я думаю, что это из более позднего C ++.

Кроме того, как насчет того, чтобы просто инициализировать его нулем во время компиляции. Может быть, сделать это постоянным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...