如何在lambda中对变量使用decltype而不捕获它?

How can I use decltype on a variable in a lambda without capturing it?

本文关键字:decltype lambda 变量      更新时间:2023-10-16

我正在尝试设计一个c++宏,需要看起来像这样:

#define MY_MACRO(OBJECT, METHOD)                            
    [](BaseClass* obj)                                      
    {                                                       
        return static_cast<decltype(OBJECT)>(obj)->METHOD();
    }

基本上是一个宏,它转换成一个lambda,在给定对象上调用给定方法。但是lambda需要将对象的基类作为参数(我的用例保证强制类型转换始终有效)。此外,要调用的方法可能不在基类上。

这个宏的用法是我有另一个不能修改的方法,声明为:

void Foo(std::function<int(BaseClass*)>);

,我需要能够调用它使用我的宏作为参数,像这样:

T x;
Foo(MY_MACRO(x, method));  // match std::function<int(T*)>

然而,宏代码不起作用,因为我没有捕获OBJECT,所以当我需要将它传递给decltype时,它不在作用域中。从概念上讲,编译器需要的所有信息都在那里…我该怎么做呢?这可能吗?

一些约束:

  1. lambda的参数需要是BaseClass。我不能使它decltype(OBJECT).
  2. 我的情况不允许我捕获对象。
  3. 我无法访问c++ 14的通用lambda捕获功能。

我需要访问对象的类型而不捕获它

你可以直接做。只有在使用命名实体时才需要捕获,而未求值的操作数(如decltype的操作数)不会使用任何东西。这很好:

void f(){
    int x; 
    []{ decltype(x) y = 0; };
}

您可以使用您想要的类型向lambda添加一个可选参数,并在该参数上使用decltype。下面是该模式的一个示例,去掉了宏:

int main() {
    int foo = 4;
    auto lambda = [](double* bar, decltype(foo)* TP = nullptr) {
        return static_cast<std::remove_pointer<decltype(TP)>::type>(*bar);
    };
    double x = 5;
    return lambda(&x);
}

我在这里得到一个指向decltype(foo)的指针,因为指针类型可以很容易地被默认为nullptr,以确保参数是可选的。如果decltype(foo)已经解析为指针类型,就像在你的情况下,如果我做对了,你就不需要它(和remove_pointer)。

试一试:

template <typename T>
auto lambda_maker(int (T::* MF)())
{
    return [](T* p) -> int { return (p->*MF)(); };
}
#define MY_MACRO(OBJ, METH) lambda_maker<decltype(OBJ)>(METH)