c++templatesarduinoc-preprocessorfastled

Can this for loop be done with the preprocessor?


My code uses a library (FastLED) which uses a templated function:

#define NUM_WIDGETS 4

Library.function<1>();
Library.function<2>();
Library.function<3>();
Library.function<4>();

I can't put this in a normal for loop since the template argument needs to be computable at compile-time. Can I do this in the preprocessor? Any other suggestion? I'd like to be able to change NUM_WIDGETS conveniently without copy-pasting these lines.


Solution

  • You can do this using templates with the help of std::index_sequence:

    constexpr size_t NUM_WIDGETS = 4;
    
    template <size_t N>
    void foo() {
        std::cout << N << '\n';
    }
    
    template <size_t... Ns>
    void call_foo_helper(std::index_sequence<Ns...>) {
        (foo<Ns>(), ...);
    }
    
    template <size_t N>
    void call_foo() {
        call_foo_helper(std::make_index_sequence<N>());
    }
    
    int main() {
        call_foo<NUM_WIDGETS>();
    }
    

    This uses C++17 fold expressions. If you don't have C++17 available, you could use a recursive template instead:

    constexpr size_t NUM_WIDGETS = 4;
    
    template <size_t N>
    void foo() {
        std::cout << N << '\n';
    }
    
    template <size_t N>
    void call_foo() {
        foo<N>();
        call_foo<N - 1>();
    }
    
    template <>
    void call_foo<0>() { }
    
    int main() {
        call_foo<NUM_WIDGETS>();
    }