Reputation: 44258
Tried to use C++11 lambda as a key accessor for boost::multi_index
:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/global_fun.hpp>
struct Foobar {
int key;
};
void func()
{
namespace mii = boost::multi_index;
typedef boost::multi_index_container< Foobar,
mii::hashed_unique< mii::global_fun< const Foobar &, int,
[]( const Foobar &f ) { return f.key; } > > > Container;
}
But getting compile error from g++ 4.8.2 and boost 1.53:
error: could not convert template argument '<lambda closure object>func()::__lambda0{}' to 'int (*)(const Foobar&)'
This answer Using Boost adaptors with C++11 lambdas suggests to convert into std::function
which does not work in this case. Is there a simple way to fix this?
Upvotes: 4
Views: 683
Reputation: 275405
Lambdas may not be used in unevaluated contexts1. I'm not sure if this qualifies as an unevaluated context, but the approach involving decltype( [](int){} )
would2.
Stateless Lambdas do not appear to have a constexpr
conversion-to-function-pointer (this is probably an oversight), otherwise this would work:
template<class T>using type=T;
template< void(*)(int) > struct test {};
constexpr type<void(int)>* f = [](int){};
int main() {
test<f> x;
}
and it might even work if you passed the lambda directly to a void(*)(int)
function-pointer parameter.
This leaves you with writing your lambda as an old-school function.
1 This is probably to make compiler's lives easier (as far as I can tell, the type of a lambda in a header file need not be consistent between compilation units under the current standard? But I'm not certain about that.)
2 This prevents you from passing it as a pure type and then invoking it. Lambdas also lack constructors. A hack whereby you construct a stateless lambda (or a reference to same) then invoke it would work in every implementation, unless the compiler noticed your slight of hand, but it is undefined behavior.
This leads to this hack:
#include <iostream>
auto f() { return [](){std::cout <<"hello world.\n";}; }
template<class Lambda>
struct test {
void operator()() const {
(*(Lambda*)nullptr)();
}
};
int main() {
test<decltype(f())> foo;
foo();
}
which is both useless and undefined behavior, but does invoke a lambda we passed as a template parameter to test
technically. (C++14)
Upvotes: 3