如何使用可变参数制作模板函数的返回类型
有人在堆栈溢出中写了一个有趣的方式来将lambda或函子捕获到自己的类中。我试图简化它,我想我已经接近了,但遇到了一些麻烦。他们的例子是:如何使用可变参数制作模板函数的返回类型
// OT => Object Type
// RT => Return Type
// A ... => Arguments
template<typename OT, typename RT, typename ... A>
struct lambda_expression {
OT _object;
RT(OT::*_function)(A...)const; // A pointer to a member function,
// specifically the operator()
lambda_expression(const OT & object) // Constructor
: _object(object),
_function(&decltype(_object)::operator()) {} // Assigning the function pointer
RT operator() (A ... args) const {
return (_object.*_function)(args...);
}
};
基本上,这可以让你去:
int captureMe = 2;
auto lambda = [=](int a, int b) { return a + b + captureMe;};
lambda_expression<decltype(lambda), int, int, int>(lambda);
我正在努力简化这一点,并认为包含在lambda_expression类指针就没有必要了,因为你可以调用函数对象本身,而不是调用指向operator()的指针。所以,我想这一点:
template <typename OT, typename ... Args> // No Return type specified
struct lambdaContainer
{
lambdaContainer(OT funcObj) : funcObj(funcObj){ }
OT funcObj; // No pointer, just the function object.
auto operator()(Args... args)
{
return funcObj(args...); // Call the function object directly
}
};
然后是这样的:
int captureMe = 2;
auto lambda = [=](int a, int b) { return a + b + captureMe; };
lambdaContainer<decltype(lambda), int, int> lam(lambda);
auto i = lam(1, 1);
// i = 4;
我在哪里写了一行:
auto operator()(Args... args)
{
return funcObj(args...);
}
显然:
decltype(auto) operator()(Args... args) //works in C++14 apparently.
但是我还是没有auto关键字,我在这样做时失败了,我想了解Args ...的工作原理。我尝试过:
decltype(funObj(Args...) operator()(Args... args) // this failed
decltype(OT(Args...) operator() (Args... args) // this failed
auto operator() (Args... args) -> decltype(funcObj(Args...)) // this failed
auto operator() (Args... args) -> decltype(OT(Args...)) // this failed
如何扩展参数以便模板可以推断返回类型?这只适用于汽车吗?
decltype(e)
接受一个表达e
并评估该表达的类型。您需要提供一个表达代表您的存储拉姆达的调用:
auto operator()(Args... args)
-> decltype(std::declval<OT>()(std::declval<Args>()...))
在这种情况下,我使用std::declval
创建可用于抵扣的目的,对象的“假实例” ,而没有实际调用任何构造函数。
让我们进一步打破这:
-> decltype(
std::declval<OT>() // create a fake instance of `OT`
( // invoke it
std::declval<Args>()... // create a fake instance of each argument
// type, expanding `Args...`
)
)
顺便说一句,你还是应该std::forward
在您的来电funcObj
的参数,因为可能有一些右值引用需要进一步传播:
auto operator()(Args... args)
{
return funcObj(std::forward<Args>(args)...);
}
这是我会猜到的最后一件事。我正在阅读declval和std :: forward。 declval我得到了,但另外两个我不明白。这很有趣,你说declval创建了一个“假”版本的对象。 – Zebrafish
@斑马鱼:'declval'所做的就是返回一个引用类型。由于'std :: declval
@斑马鱼:我应该进一步澄清什么东西? –
这可能不会正确,但我建议你阅读[良好的C++书](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list),在特别是一些先进的。在这样的片段中学习C++非常困难。 –