Есть ли способ вызвать функцию, ожидающую указатель без создания переменной? - PullRequest
0 голосов
/ 28 апреля 2018

У меня есть вызов этой функции:

uint32_t func(uint32_t* a, uint32_t b)

Я хочу назвать его целочисленным литералом, например:

func(0, b);

, где b - это uint32_t.

Есть ли способ сделать это без создания промежуточной переменной?
То есть Я хочу избежать этого:

uint32_t a = 0;
func(a, b);

Ответы [ 2 ]

0 голосов
/ 28 апреля 2018

Класс помощника:

struct int_ptr {
    int v;

    operator int *() { return &v; }
};

int foo(int *a, int b);

void bar()
{
    foo(int_ptr{0}, 0);
}

В результате создается временный класс int_ptr, инициализирующий его член v равным 0. Он передается в качестве параметра функции, которая принимает int *, а int_ptr обеспечивает подходящее operator * метод, который передает правильный указатель на функцию.

Весь этот карточный домик зависит от того факта, что временный int_ptr существует до конца вызова функции. Вы должны выбрать имя для вспомогательного класса, чтобы подчеркнуть этот факт. Если вы всегда используете его, чтобы передать указатель на 0 для foo, то укажите это по буквам:

struct zero_value_to_foo {
    int v=0;

    operator int *() { return &v; }
};

int foo(int *a, int b);

void bar()
{

    foo(zero_value_to_foo{}, 0);
}

Так что использование его в других контекстах будет выглядеть очень неуместно, т.е.

int *p=zero_value_to_foo{};

Это компилируется, но оставляет вас с висящим указателем; но, надеюсь, метка zero_value_to_foo дает сигнал, что здесь что-то не так.

Еще одна маленькая вещь, которую вы можете сделать, чтобы избежать злоупотребления этим, - использовать для оператора квалификатор ref :

struct zero_value_to_foo {
    int v=0;

    operator int *() && { return &v; }
};

С этим

foo(zero_value_to_foo{}, 0);

все еще компилируется, но не так:

zero_value_to_foo zero{};

foo(zero, 0);

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

0 голосов
/ 28 апреля 2018

Я предполагаю, что вы хотите передать указатель на целое число 0, а не указатель 0 (NULL).

Если вы не против распределения динамической памяти, вы можете сделать это:

func(new uint32_t(0), b);

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

В качестве альтернативы, вы можете использовать R-значение ссылки (c ++ 11). Затем вы можете использовать адрес ссылки в качестве указателя внутри вашей функции.

Синтаксис R-значения:

uint32_t func(uint32_t &&a, uint32_t b);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...