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

时间:2016-09-13 22:01:48

标签: c++ lambda decltype

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

SELECT 
    CAST(fwd.EmployeeId AS varchar) + ', ' + 
    fwd.Vacation_Kind + ', ' + 
    CAST(fwd.[Value] as varchar) +  
    CASE WHEN adj.Value IS NULL THEN '' ELSE ', ' + CAST(adj.Value AS varchar) END
FROM 
    @employeeVacations fwd
    LEFT OUTER JOIN @employeeVacations adj ON 
        adj.EmployeeId = fwd.EmployeeId)
        AND 
        adj.Vacation_Kind = 'SL')
        AND 
        adj.Vacation_Type = 'Adjust'
        AND 
        adj.CreationDate = '2016-07-01'
WHERE 
    --fwd.EmployeeId = 26 
    --AND 
    fwd.Vacation_Kind = 'SL' 
    AND 
    fwd.Vacation_Type = 'Forward'
    AND 
    fwd.CreationDate = '2016-08-01'

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

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

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

我需要能够使用我的宏作为参数来调用它:

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

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

一些限制:

  1. lambda的参数需要是BaseClass。我不能使它成为decltype(OBJECT)。
  2. 我的情况不允许我捕获OBJECT。
  3. 我无法访问广义lambda捕获的C ++ 14特性。

3 个答案:

答案 0 :(得分:4)

  

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

你可以直接做到。只有当您使用命名实体时,才需要捕获,而未评估的操作数(如decltype的操作数)不会使用任何东西。这非常好:

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

答案 1 :(得分:1)

您可以使用所需的类型向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)。

答案 2 :(得分:1)

这是一次尝试:

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)