I was trying to implement a certain type trait, but faced this following error.
Here is a simple program that shows the behavior:
#include <iostream>
template<typename T>
struct my_floating_point // just to make a case
{
// static constexpr bool value = std::is_floating_point_v<T>;
// THIS WORKS
static constexpr bool value = []()
{
if constexpr(std::is_floating_point_v<T>) { return true; }
else { return false; }
}; // compilation error
};
int main()
{
std::cout << my_floating_point<int>::value << std::endl;
std::cout << my_floating_point<double>::value << std::endl;
std::cout << my_floating_point<char>::value << std::endl;
}
The commented line works just fine.
However, the uncommented piece of code gives this warning with g++
:
g++ -std=c++17 -O3 main.cpp -Wall -Wextra -pedantic
main.cpp: In instantiation of ‘constexpr const bool my_floating_point<int>::value’:
main.cpp:18:39: required from here
main.cpp:9:24: warning: the address of ‘static constexpr bool my_floating_point<int>::<lambda()>::_FUN()’ will never be NULL [-Waddress]
static constexpr bool value = []()
^~~~~
main.cpp:9:24: warning: the address of ‘static constexpr bool my_floating_point<int>::<lambda()>::_FUN()’ will never be NULL [-Waddress]
And running it outputs
1
1
1
What is wrong?
Note: clang++
for some reason doesn't give warning, but outputs the same.
[]()
{
// ...
}
A lambda expression evaluates to an instance of an anonymous type. That's what a lambda really is: an object whose type is unspecified. Attempting to assign an instance of this object to a bool
is not valid C++.
The good news is that this anonymous type has an operator()
overload, that just happens, accidentally, to return a bool. So, for example, this will work:
static constexpr bool value = []()
{
if constexpr(std::is_floating_point_v<T>) { return true; }
else { return false; }
}(); // compiles just fine.