Создать и вызвать пустую функцию - PullRequest
0 голосов
/ 26 февраля 2019

Учитывая сигнатуру функции (например, из аргумента template), я хочу создать (не встроенную) функцию с этой сигнатурой, а затем вызвать ее.

Следующее должно прояснить это намерение.Как написано, это недопустимо, поскольку отмеченная строка фактически генерирует пустой указатель на функцию, а не пустую функцию:

template <typename Function, typename... Args>
void foo(Args... args) {
    Function fn_trivial = {}; //incorrect; should be empty function, not null function
    fn_trivial(args...);
}

Как я могу создать здесь функциональный объект?


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

1 Ответ

0 голосов
/ 26 февраля 2019

Вы не можете создать локальную функцию в C ++.Вы можете создать локальный тип объекта и определить / вызвать его operator(), или использовать лямбду, но в этот момент вы также можете поместить его наружу как реальную функцию:

template <typename TypeRet, typename... Args>
TypeRet empty_function(Args... args) {
    return TypeRet();
}

template <typename Function, typename... Args>
void foo(Args... args) {
    empty_function<decltype( std::declval<Function>()(args...) )>(args...);
}

(рассмотрите возможность добавленияstd::forward, по желанию.)

Обратите внимание, что любой стоящий компилятор удалит вызов, даже если он помечен как недействительный.Это потому, что, хотя функция не является встроенной, она ничего не делает, и поэтому может быть исключена полностью.Вы можете обойти это несколькими способами, но использование переменной volatile переносимо на Clang, GCC, ICC и MSVC:

#ifdef _MSC_VER
    #define NOINLINE __declspec(noinline)
#else
    #define NOINLINE __attribute__((noinline))
#endif
template <typename TypeRet, typename... Args>
NOINLINE TypeRet empty_function(Args... args) {
    TypeRet volatile a = TypeRet();
    return a;
}

Смотрите вживую.

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