首页 > 解决方案 > C++11 将 lambda 表达式注入类

问题描述

常见类型擦除 都是 C++14 或 C++17。当我坚持使用 C++11 时,我考虑编写自己的。问题是我无法使以下代码工作:

struct Drawable {
  void draw() const { poly_call<0>(*this); }

  //How has this macro to look like?
  MAKE_VTABLE([](T const& self) { self.draw(); })
};

//My library-code:
using VTableForT = decltype(Drawable::GetVTable<T>());

澄清一下,在 C++14 中,它可能看起来像:

#define MAKE_VTABLE(lambda)         \
    template<class T>               \
    static auto GetVTable() {       \
        return lambda;              \
    }

但自动返回在 C++11 中尚不可用。有任何想法吗?对我来说,GetVTable 是静态函数还是静态变量都无关紧要。我只想让用户用他的 lambda 表达式调用宏,然后在我的库代码中获取它的类型。

标签: c++11

解决方案


首先,如果您希望能够将 Drawable 传递给 GetVTable,则必须将 draw 标记为 const,因为参数标记为 const(在返回的 lambda 中),我们只能在内部调用 const 标记的函数。

现在到实际的问题。你有什么要求?您是否一定要从 GetVTable 返回一个 lambda,或者另一个 Callabe 会这样做吗?从函数返回 lambdas 总是很麻烦。一个可能的修复来自使用 std::function

返回类型将变为std::function <void(T const&)>

因此代码看起来像:

#define MAKE_VTABLE(lambda)                              \
template<class T>                                        \
static std::function<void(T const&)> GetVTable() {       \
    return lambda;                                       \
}

请记住为此使用#include 功能。

由于您的 return lambda 没有捕获任何内容,因此它也可以转换为裸函数指针。

// A helper using declaration for return type
template <class T>
using ret_t = void (*) (T const&);

// The macro
#define MAKE_VTABLE(lambda)                              \
template<class T>                                        \
static ret_t<T> GetVTable() {                            \
    return lambda;                                       \
}

当然,您可以取消辅助函数并直接将其编写在 auto 的位置。


推荐阅读