Подтвердить что ты не робот

Стандартная функция библиотеки для запуска функции только один раз

Существует ли какая-то стандартная библиотечная функция/класс по отношению к этому выражению лямбда:

void some_func(int some_arg, float some_other_arg){
    static int do_once = ([](){
        // will be run once upon first function call but never again
        return 0; // dummy return value
    })();
    // will always run
}

Похоже на такой взлом, чтобы написать это, но я не могу придумать другой способ сделать это иначе, чем просто вызвать функцию в main, но то, что я на самом деле делаю, зависит от параметров шаблона, и мне нужно чтобы он был как можно более общим.

В контексте:
Я регистрирую функцию с atexit для каждого другого параметра шаблона, но только один раз: при первом вызове.

4b9b3361

Ответ 1

Возможно, вы должны использовать std::call_once, найденный в <mutex>.
Примеры использования здесь

Ответ 2

Я пошел с опцией std::call_once, и он отлично работает.

Для этого я переписал свою функцию так:

template<typename T>
void my_function(){
    static std::once_flag once;

    // function body (may return)

    // only called if rest of function successful
    std::call_once(once, [](){/* special sauce */});
}

@cdhowie, я не думаю, что вы вполне понимаете, что я имею в виду под static, это почти противоположно глобальному.

Ответ 3

Как указано в комментариях, std::call_once() - это опция, но вы не можете заставить глобальную глобальную или только одну функцию получать, даже если вы предоставляете разные аргументы шаблона. Похоже, вы хотите вызвать функцию только один раз для заданных аргументов шаблона.

Если это так, вы можете сделать функцию статической частью класса шаблона, все еще используя механизм std::call_once():

template <typename T>
class initializer
{
public:
    static void call();

private:
    static void target();

private:
    static std::once_flag flag;
};

template <typename T>
void initializer<T>::call()
{
    std::call_once(flag, target);
}

template <typename T>
void initializer<T>::target()
{
    // Your code goes here.
}

template <typename T>
std::once_flag initializer<T>::flag;

Теперь вы можете вызвать initializer<T>::call() с разными типами T, и вы гарантированно сделаете не более одного вызова на отдельный T.