使用传入构造函数的 lambda 初始化 class,C++11

Initializing class with a lambda passed into constructor, C++11

让我们考虑以下示例:

#include <functional>
#include <iostream>

using namespace std;

class Caller {
 public:
  Caller(function<void()> callback) {
    callback();
  }
};

main() {
#if defined(ONELINER)
  Caller caller = [] { cout << "test"; };
#else
  function<void()> fun = [] { cout << "test"; };
  Caller caller(fun);
#endif  // defined(ONELINER)
}

如果我们简单地尝试编译它(使用 -std=c++11 标志)它会愉快地完成,并在 运行 时显示 test。然而,如果我们定义 ONELINER 宏编译将失败:

prog.cpp: In function 'int main()':
prog.cpp:17:40: error: conversion from 'main()::<lambda()>' to non-scalar type 'Caller' requested
   Caller caller = [] { cout << "test"; };

我理解这是由于lambda到std::function的隐式转换,然后是std::functionCaller的隐式转换造成的,我们无法进行2次转换同时

是否有可能使语法 Class object = lambda; 起作用?我问是因为我最近出于教育原因编写了自己的小型测试框架,我认为:

UNIT_TEST(test_name) {
  // test content
};

优雅多了
UNIT_TEST_BEGIN(test_name)
  // unit test
UNIT_TEST_END()

前者可以通过将 lambda 传递给 UnitTest 构造函数来实现。但是对于我描述的问题,我不得不使用肮脏的解决方法,例如:

#define UNIT_TEST(test_name) \
    ::std::function<void(::Helper*)> test_name_helper; \
    ::UnitTest test_name ## _test = \
        test_name_helper = \
        [&] (::Helper* helper)

而且看起来一点也不优雅。但即使这可以在没有 lambda 的情况下完成,我仍然很好奇是否可以实现 Class object = lamda; 语法。

修改构造函数为:

template<typename CB>
Caller(CB callback) {
  callback();
}

这将允许它接受 任何 可调用参数,无论是 lambda、std::function、函数指针还是仿函数。

不幸的是,构造函数也将接受任何 other 类型,但是当 callback 不能像函数一样 "called" 时给出编译器错误.