Compiletime for each with custom functions

*爱你&永不变心* 提交于 2019-12-04 18:39:00

Using a lambda I managed to get pretty close to what you intend, even though I failed to provide an exact match:

template<typename Executor, typename Data, typename ... Functors>
void for_each(Executor executor, Data const& data, Functors ... functors)
{
    // C++17 fold expression:
    (executor(functors, data), ...);
}

class C0
{
public:
    void test0(int) const { std::cout << "00" << std::endl; }
    void test1(int) const { std::cout << "01" << std::endl; }
};
class C1
{
public:
    void test0(int) const { std::cout << "10" << std::endl; }
    void test1(int) const { std::cout << "11" << std::endl; }
};

int main()
{
    for_each([](auto const& c, int data) { c.test0(data); }, 7, C0(), C1());
    for_each([](auto const& c, int data) { c.test1(data); }, 7, C0(), C1());
    return 0;
}

Some observations.

1) if you want a compile time execution, you have to use constexpr.

So your compile_time_for_each() must be defined constexpr if you want that can be executed compile time

template <typename data_t, typename... type_list_t>
constexpr void compile_time_for_each (data_t const & data, type_list_t &... objects)
 { /* some potentially compile time code */  }

2) a constexpr function can be executed both compile time and run time; if you want impose that is executed compile-time... maybe there are other ways but the simplest mode come in my mind is return a value from the function

template <typename data_t, typename... type_list_t>
constexpr int compile_time_for_each (data_t const & data, type_list_t &... objects)
 {
   /* some potentially compile time code */

   return 1;
 }

and use the returned value to initialize a constexpr variable

constexpr auto x = compile_time_for_each(data, functor_1, functor_2);

3) for a compile time execution, you needs compile-time values, so define data as constexpr

constexpr int data = 42;

or its use prevents the compile time execution.

4) there is no needs of recursion: you tagged C++17 so you can use template folding; by example

template <typename D, typename ... Fs>
constexpr int compile_time_for_each (D const & data, Fs const & ... funcs)
 {
   (std::apply(funcs, data), ...);

   return 0;
 }

5) iostream input/output code isn't compatible with compile-time execution; so the following lambdas

 auto functor_1 = [] (int data) {std::cout << data;};
 auto functor_2 = [] (int data) {data++; std::cout << data;};

can't be executed compile-time.


The following is a C++17 example

#include <tuple>

template <typename D, typename ... Fs>
constexpr int ct_for_each (D const & data, Fs const & ... funcs)
 {
   (std::apply(funcs, data), ...);

   return 0;
 }

int main ()
 {
   constexpr int data = 42;

   auto constexpr functor_1 = [] (int data) { /* some_code_1 */ };
   auto constexpr functor_2 = [] (int data) { /* some_code_2 */ };

   // compile time error if you define functor_1 as follows
   // auto constexpr functor_1 = [] (int data) { std::cout << data << std::endl; };

   constexpr auto x = ct_for_each(std::make_tuple(data), functor_1, functor_2);

   (void)x; // to avoid "unused variable 'x'" warning
 }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!