使用带有boost::multi_index的C++11 lambda

Using C++11 lambda with boost::multi_index

本文关键字:index C++11 lambda multi boost      更新时间:2023-10-16

尝试使用C++11 lambda作为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;
}

但是从g++4.8.2和boost1.53:中得到编译错误

error: could not convert template argument '<lambda closure object>func()::__lambda0{}' to 'int (*)(const Foobar&)'

这个答案使用C++11 lambdas的Boost适配器建议转换为std::function,在这种情况下不起作用。有没有一个简单的方法来解决这个问题?

Lambdas不能用于未评估的上下文1。我不确定这是否符合未评估的上下文,但涉及decltype( [](int){} )的方法将2

无状态Lambdas似乎没有constexpr到函数指针的转换(这可能是一个疏忽),否则这将起作用:

template<class T>using type=T;
template< void(*)(int) > struct test {};
constexpr type<void(int)>* f = [](int){};
int main() {
  test<f> x;
}

如果您将lambda直接传递给void(*)(int)函数指针参数,它甚至可能起作用。

这就让你把lambda写成一个老派函数。


1这可能是为了让编译器的生活更轻松(据我所知,在当前标准下,头文件中lambda的类型在编译单元之间不需要一致?但我对此不确定。)

2这会阻止您将其作为纯类型传递,然后再调用它。Lambdas也缺少构造函数。构建一个无状态lambda(或对其的引用)然后调用它的破解方法在每个实现中都有效,除非编译器注意到你的疏忽,但这是未定义的行为。

这导致了这次黑客攻击:

#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();
}

这既是无用的,也是未定义的行为,但在技术上确实调用了我们作为模板参数传递给test的lambda。(C++14)