Класс помощника:
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);
Чем больше можно сделать, чтобы затруднить использование этого, кроме как для контекста, тем меньше возможностей для проникновения ошибок.