I have a lambda that ignores its int
parameter and always returns a constant.
If I mark it consteval
, compilation fails because.
The compiler complains about invoking the consteval
lambda with a non-const parameter.
But what does the parameter has to do with the lambda?
From CompilerExplorer:
source:3:16: error: the value of 'i' is not usable in a constant expression 5 | lambda(i);
void bar (auto lambda, int start, int end) {
for (int i=start; i<end; i) {
lambda(i);
}
}
int main( )
{
auto foo = [] (int) consteval { return 2;};
bar(foo, 1, 9);
return 0;
}
CodePudding user response:
One way to solve this(and the simplest) is to change the parameter type of the lambda to int&
so that it doesn't need to read the value, as shown below:
int main( )
{//-------------------v------------------------->reference added
auto foo = [] (int&) consteval { return 2;};
bar(foo, 1, 9);
return 0;
}
Here is another contrived example that has similar behavior:
template<typename T>
consteval int func(const T) //note NO REFERENCE HERE
{
return std::is_integral<T>::value;;
}
template<typename T>
//-----------------------v----->note the reference here
consteval int bar(const T&)
{
return std::is_integral<T>::value;;
}
int main()
{
int p = 2;
//constexpr int d = func(p); //doesn't work
constexpr int f = bar(p); //works
}
CodePudding user response:
You can also add an explicit check. Not the most elegant solution, but yeah:
#include <type_traits>
void bar(auto lambda, int start, int end) {
for (int i = start; i < end; i) {
if constexpr (std::is_invocable_v<decltype(lambda)>) {
lambda();
} else {
lambda(i);
}
}
}
int main() {
bar([] () consteval { return 2; }, 1, 9);
bar([](int) { return 2; }, 1, 9);
return 0;
}