Is there a way to pass a `constexpr` value into lambda so that it remains `constexpr` inside that lambda?

  • A+
Category:Languages

Here's what I want to do; posting the whole code because it's not too long and also to demonstrate the specific task I'm trying to solve. Basically, I need a way to iterate values from parameter pack by index (the index part is important, even though it's not required in this example).

#include <iostream> #include <tuple> #include <type_traits>  template <int First, int Last, typename Functor> constexpr void static_for(Functor&& f) {     if constexpr (First < Last)     {         f(std::integral_constant<int, First>{});         static_for<First + 1, Last, Functor>(std::forward<Functor>(f));     } }  template <size_t index, typename... Args> auto value_by_index(Args&&... args) noexcept {     return std::get<index>(std::forward_as_tuple(std::forward<Args>(args)...)); }  template <typename... ValueTypes> void traverse(ValueTypes... values) {     static_for<0, sizeof...(ValueTypes)>([&](int i) {         auto v = value_by_index<static_cast<size_t>(i), ValueTypes...>(values...);         std::cout << v << std::endl;     }); }  int main() {     traverse(0.0f, 1, 3.33, "str");      return 0; } 

The compiler error, of course, is:

<source>:24:71: error: 'i' is not a constant expression 

If lambdas could have explicit template arguments, i would be such an argument and it would be obvious to the compiler that it's known at compile time. But that's not how lambdas work.

If you want to treat it as an X-Y problem, I suppose I don't specifically need to call a lambda inside my static_for, but I do need to call some piece of code that can access parameter pack(s) of traverse by index, and if traverse was a member function, I need to have access to its this.

Try it online: https://godbolt.org/z/eW4rnm

 


Use a generic lambda and a constexpr conversion operator :

template <typename... ValueTypes> void traverse(ValueTypes... values) {     static_for<0, sizeof...(ValueTypes)>([&](auto I)     //                                       ~~~^     {         auto v = value_by_index<I>(values...);         //                     ~^~         std::cout << v << std::endl;     }); } 

DEMO

Use a template parameter list for the lambda expression :

template <typename... ValueTypes> void traverse(ValueTypes... values) {     static_for<0, sizeof...(ValueTypes)>([&]<int I>(std::integral_constant<int, I>)     //                                       ~~~~^                             ~^~     {         auto v = value_by_index<I>(values...);         //                     ~^~         std::cout << v << std::endl;     }); } 

DEMO 2

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: