I'm trying to create a curried interface using nested constexpr lambdas, but the compiler does not consider it to be a constant expression.
namespace hana = boost::hana;
using namespace hana::literals;
struct C1 {};
template < typename T,
std::size_t size >
struct Array {};
constexpr auto array_ = [] (auto size) {
return [=] (auto type) {
return hana::type_c<Array<typename decltype(type)::type, size()>>;
};
};
int main() {
constexpr auto c1 = hana::type_c<C1>;
constexpr auto test = hana::type_c<Array<typename decltype(c1)::type, hana::size_c<100>()>>;
constexpr auto test2 = array_(hana::size_c<100>)(c1);
}
I post a question earlier because I found a different minimal example, but it wasn't enough.
Error:
test2.cpp: In instantiation of ‘<lambda(auto:1)>::<lambda(auto:2)> [with auto:2 = boost::hana::type_impl<C1>::_; auto:1 = boost::hana::integral_constant<long unsigned int, 100>]’:
test2.cpp:31:54: required from here
test2.cpp:20:16: error: ‘__closure’ is not a constant expression
return hana::type_c<Array<typename decltype(type)::type, size()>>;
^~~~
test2.cpp:20:16: note: in template argument for type ‘long unsigned int’
test2.cpp: In function ‘int main()’:
test2.cpp:31:18: error: ‘constexpr const void test2’ has incomplete type
constexpr auto test2 = array_(hana::size_c<100>)(c1);
__closure is not a constant expression
: if someone could explain me this error that would be a great help. I ran into that error before but can't remember why.
constexpr lambda expressions in C++ Visual Studio 2017 version 15.3 and later (available in /std:c++17 mode and later): A lambda expression may be declared as constexpr or used in a constant expression when the initialization of each data member that it captures or introduces is allowed within a constant expression.
Even though try blocks and inline assembly are allowed in constexpr functions, throwing exceptions or executing the assembly is still disallowed in a constant expression.
All lambdas definitely are NOT inline. But all lambdas definitely are inplace. The inline is reserved for the compiler specific optimization which is not much correlated with the inplace coding like lambdas does.
I reduced your test case to this:
#include <type_traits>
constexpr auto f = [](auto size) {
return [=](){
constexpr auto s = size();
return 1;
};
};
static_assert(f(std::integral_constant<int, 100>{})(), "");
int main() { }
As said in the comments above, this happens because size
is not a constant expression from within the function body. This is not specific to Hana. As a workaround, you can use
constexpr auto f = [](auto size) {
return [=](){
constexpr auto s = decltype(size)::value;
return 1;
};
};
or anything similar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With