Информация об изменениях

Сообщение Zero-cost метод вызвать функцию для каждого шаблонного парам от 14.10.2020 21:10

Изменено 14.10.2020 21:11 Molchalnik

Zero-cost метод вызвать функцию для каждого элемента шаблона
Disclaimer: Вопрос баян и велосипед, но у меня свой интерес, заточенный под определённую специфику применения.

Задача: изобрести zero-cost метод вызвать функцию для каждого элемента шаблона

Классика — рекурсия на шаблонах — не подходит, потому что генерит кучу лишних функций и за счёт раздувания кода её нельзя считать zero-cost. Плюс рекурсивные вызовы лишних функций.

Мой вариант тут (копия под катом), но он мне не нравится, т.к. работает только для функторов, и даже лямбду без бубна не подставишь. А хотелось бы иметь возможность использовать и для функции. Или хотя бы, чтобы были две функции — одна для функтора, другая для шаблонной функции
  Копия кода
#include <iostream>
#include <string>
#include <vector>
#include <tuple>

template <typename Arg> struct Print { 
    void operator()( Arg arg ) { std::cout << std::forward<Arg>(arg)<<std::endl; }
};

template <typename Arg> void Print2 ( Arg arg ) { std::cout << std::forward<Arg>(arg)<<std::endl; }


template < template <typename> class Callback, typename... Args> struct ForEachHelper {
    void operator()( Args&& ... args) {        
       (    (   Callback<decltype(std::forward<Args>(args))>()( std::forward<Args>(args) )   ),...    );
    }
};

template <template <typename> class Callback, typename... Args> void ForEach( Args&&... args ) {
    ForEachHelper<Callback, Args...>()( std::forward<Args>(args)... );
}

int main()
{
    ForEach<Print>( "aaa", 14, 0.34 );
    return 0;
}


Можно ли сделать поэлегантней?

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

Вот ещё несколько вариантов на стэковерфлоу
Zero-cost метод вызвать функцию для каждого шаблонного парам
Disclaimer: Вопрос баян и велосипед, но у меня свой интерес, заточенный под определённую специфику применения.

Задача: изобрести zero-cost метод вызвать функцию для каждого шаблонного параметра

Классика — рекурсия на шаблонах — не подходит, потому что генерит кучу лишних функций и за счёт раздувания кода её нельзя считать zero-cost. Плюс рекурсивные вызовы лишних функций.

Мой вариант тут (копия под катом), но он мне не нравится, т.к. работает только для функторов, и даже лямбду без бубна не подставишь. А хотелось бы иметь возможность использовать и для функции. Или хотя бы, чтобы были две функции — одна для функтора, другая для шаблонной функции
  Копия кода
#include <iostream>
#include <string>
#include <vector>
#include <tuple>

template <typename Arg> struct Print { 
    void operator()( Arg arg ) { std::cout << std::forward<Arg>(arg)<<std::endl; }
};

template <typename Arg> void Print2 ( Arg arg ) { std::cout << std::forward<Arg>(arg)<<std::endl; }


template < template <typename> class Callback, typename... Args> struct ForEachHelper {
    void operator()( Args&& ... args) {        
       (    (   Callback<decltype(std::forward<Args>(args))>()( std::forward<Args>(args) )   ),...    );
    }
};

template <template <typename> class Callback, typename... Args> void ForEach( Args&&... args ) {
    ForEachHelper<Callback, Args...>()( std::forward<Args>(args)... );
}

int main()
{
    ForEach<Print>( "aaa", 14, 0.34 );
    return 0;
}


Можно ли сделать поэлегантней?

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

Вот ещё несколько вариантов на стэковерфлоу