【问题标题】:Using C++11 lambda with boost::multi_index将 C++11 lambda 与 boost::multi_index 一起使用
【发布时间】:2014-09-11 14:38:40
【问题描述】:

尝试使用 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 和 boost 1.53 得到编译错误:

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

这个答案Using Boost adaptors with C++11 lambdas 建议转换成std::function 在这种情况下不起作用。有没有简单的方法来解决这个问题?

【问题讨论】:

    标签: c++ c++11 boost lambda


    【解决方案1】:

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

    无状态 Lambda 似乎没有 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 这可以防止您将它作为纯类型传递然后调用它。 Lambda 也缺少构造函数。构造一个无状态 lambda(或对它的引用)然后调用它的 hack 将在每个实现中起作用,除非编译器注意到你的轻微手,但它是未定义的行为。

    这导致了这个 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();
    }
    

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

    【讨论】:

    • 感谢您的回答。您认为有没有办法在 boost 中修复它(例如创建特殊的密钥提取器)或者它需要更改语言?
    • @Slava 语言据我所知:将无状态 lambda 转换为函数指针 constexpr,我们可能会很好。
    猜你喜欢
    • 2012-08-06
    • 2015-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    • 2017-08-11
    • 1970-01-01
    相关资源
    最近更新 更多