【问题标题】:C++0x lambda, how can I pass as a parameter?C++0x lambda,如何作为参数传递?
【发布时间】:2010-07-23 18:36:22
【问题描述】:

请看以下C++0x lambda相关代码:

typedef uint64_t (*WEIGHT_FUNC)(void* param);
typedef std::map<std::string, WEIGHT_FUNC> CallbackTable;

CallbackTable table;
table["rand_weight"] = [](void* param) -> uint64_t
{
  return (rand() % 100 + 1);
};

我收到一个错误(在 Visual Studio 2010 中),无法将 lambda 转换为 WEIGHT_FUNC 的类型。我也知道答案:使用std::function object:

typedef std::function<uint64_t (void*)>  WEIGHT_FUNC;

但是,我也想知道如何在不使用 std::function 的情况下接收 lambda 类型。应该是什么类型的?

【问题讨论】:

  • auto 只会用于自动确定类型,它不是变体类型,它不能是参数。
  • 您使用的是哪个编译器?似乎您的编译器在 lambda 方面是非标准的,它们应该能够隐式转换为函数指针(在这种情况下。)
  • g++ 4.5 没问题,所以我猜是 VC10,我已经看到了一些 lambda 错误。
  • @James: 啊,你当然有一个漏洞——我应该知道 :)

标签: c++ lambda c++11


【解决方案1】:

到函数指针的转换相对较新:它是在 2010 年 2 月 15 日与N3043 一起引入的。

虽然例如GCC 4.5 实现了它,Visual Studio 10 于 2010 年 4 月 12 日发布,因此没有及时实现它。正如 James 指出的那样,这个 will be fixed 在未来的版本中。

目前您必须使用此处提供的替代解决方案之一。

从技术上讲,类似以下解决方法的方法可行,但如果没有可变参数模板,概括它就没有乐趣(Boost.PP 来救援...),并且没有安全网可以防止传递捕获 lambda:

typedef uint64_t (*WeightFunc)(void* param);

template<class Func> WeightFunc make_function_pointer(Func& f) {
    return lambda_wrapper<Func>::get_function_pointer(f);
}

template<class F> class lambda_wrapper {
    static F* func_;
    static uint64_t func(void* p) { return (*func_)(p); }    
    friend WeightFunc make_function_pointer<>(F& f);    
    static WeightFunc get_function_pointer(F& f) {
        if (!func_) func_ = new F(f);
        return func;
    }
};

template<class F> F* lambda_wrapper<F>::func_ = 0;

// ...
WeightFunc fp = make_function_pointer([](void* param) -> uint64_t { return 0; });

【讨论】:

  • 值得一提的是,函数指针的转换仅适用于无状态的lambda函数,它们无法捕获词法范围。
  • 转换为函数指针似乎不适用于模板代码中的 g++ 4.5 (tinyurl.com/3y6hkyq)
【解决方案2】:

如果你真的坚持不使用function&lt;&gt;那么你可能会使用decltype:

typedef decltype([](void*)->uint_64{return 0;}) my_lambda_type;

我真的不建议这样做,因为你极大地限制了自己,我什至不知道两个具有相同签名的 lambda 是否保证是相同的类型。

【讨论】:

  • 是否保证生成的类型与在其他地方编写完全相同的 typedef 相同?我认为您不应该假设该类型依赖于签名......但也许我错了。
  • 旧答案,我知道,但 lambda 表达式不能出现在未评估的上下文中。 (我认为您提出的理由是:由于每个 lambda 表达式都是唯一的、未指定的类型,因此无法保证在未评估的上下文中获得任何特别有意义的答案。)
【解决方案3】:

尝试(未测试):

#include <function>

typedef std::function< int64_t (void*) > weight_func;
typedef std::map<std::string, weight_func > CallbackTable;

我认为除了使用 std::function 或等效方法之外,没有其他方法可以做到这一点。

【讨论】:

  • 不要使用std::function&lt;R (*)(T)&gt;,使用std::function&lt;R (T)&gt;
  • 我已经知道如何使用 std::function(请再次查看我的帖子)。我想知道是否有办法使用 std::function 将 lambda 转换为函数指针。
  • 奇怪,我必须包含 ,而不是 VS2010 的
猜你喜欢
  • 2011-04-21
  • 1970-01-01
  • 2016-04-21
  • 1970-01-01
  • 2013-03-29
  • 2018-10-26
  • 1970-01-01
  • 2011-09-04
  • 2016-08-21
相关资源
最近更新 更多