我正在尝试设计一个需要看起来像这样的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时它不在范围内。从概念上讲,编译器需要的所有信息都在那里......我怎么能这样做?有可能吗?
一些限制:
答案 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)