С++ 11 встроенных лямбда-функций без шаблона

Я хочу передать лямбда-функцию как обратный вызов другой функции:

void test(const std::function<void()> fn){
    fn();
}

Это работает, все нормально. Но. Он не встраивает его, независимо от того, насколько высокий уровень оптимизации компилятора я использую:
доказательство

И когда я играю некоторое время, я обнаружил, что с шаблоном -it становится inlined:

template<typename T>     
void test2(T fn){
     fn();
}

proof_2

Итак... Есть ли способ сделать его встроенным без шаблонов? И почему он становится встроенным в объявление шаблона? Только тип функции передается как аргумент шаблона, а не сама функция.

Ответ 1

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

auto f1 = [] { return 1; };
auto f2 = [] { return 1; };
static_assert(!std::is_same<decltype(f1), decltype(f2)>::value, "He wrong");

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

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

void test(void (*fn)()) {
    fn();
}