2010-07-23 38 views
17

请看看下面的C++ 0x的λ相关代码: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),该拉姆达不能转换为WEIGHT_FUNC类型。我也知道了答案:用std::function object

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

不过,我也想知道我怎么能接受的λ的类型,除非使用std::function。它应该是什么类型?

+1

'auto'? auto_ – kennytm 2010-07-23 18:39:38

+2

auto只是用于自动确定类型,它不是变体类型,它不能是参数。 – Klaim 2010-07-23 18:41:36

+2

您正在使用哪种编译器?似乎你的编译器对于lambda来说是非标准的,它们应该能够隐式地转换成函数指针(在这种情况下) – GManNickG 2010-07-23 19:03:50

回答

20

为一个函数指针的转化是相对较新的:将其用N3043 2月15日推出,2010年

虽然例如GCC 4.5实现它,Visual Studio 10于2010年4月12日发布,因此没有及时实施。正如詹姆斯指出的,在未来的版本中这个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; }); 
+8

值得一提的是,转换为函数指针只是无状态的lambda函数,它们不能捕获词法范围。 – 2010-07-24 10:08:01

+0

转换为函数指针似乎不适用于g ++ 4.5模板代码(http://tinyurl.com/3y6hkyq) – rafak 2010-08-06 00:08:23

+0

请参阅http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45080 。 – 2010-08-07 14:44:40

-1

尝试(未测试):

#include <function> 

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

我不认为有任何其他方式做到这一点,而不是使用std ::函数或同等学历。

+0

感谢修复sbi – Klaim 2010-07-23 18:56:03

+3

不要使用'std :: function ',使用'std :: function '。 – 2010-07-23 19:01:49

+0

对!修正了,谢谢! – Klaim 2010-07-23 19:28:28

1

如果你真的坚持不使用function<>那么你很可能decltype:

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

我真的不推荐,虽然这一点,因为你大大限制自己,我甚至不知道如果两个具有相同签名的lambda保证是相同的类型。

+0

是否保证生成的类型将是相同比如果你写的确实相同的typedef某处其他?我认为你不应该认为这个类型是签名依赖的......但也许我错了。 – Klaim 2010-07-23 19:30:07

+0

在GCC中不起作用。 – 2010-08-28 19:53:36

+1

旧的答案,我知道,但lambda表达式不能出现在未评估的上下文中。 (我认为你提出的理由是:因为每个lambda表达式都是一个唯一的,未指定的类型,所以你不能保证任何特别有意义的答案和一个未被评估的上下文。) – GManNickG 2011-02-04 06:22:25

相关问题