gpt4 book ai didi

c++ - 如何使用可变参数使模板推断函数的返回类型

转载 作者:太空狗 更新时间:2023-10-29 22:56:56 24 4
gpt4 key购买 nike

stack overflow 上的某个人写了一个有趣的方法来将 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

如何扩展 Args 参数以便模板可以推导出返回类型?只有自动才能做到这一点吗?

最佳答案

decltype(e) 接受一个表达式 e 并求出该表达式 的类型。您需要提供一个表达式来表示对您存储的 lambda 的调用:

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...`
)
)

live example on wandbox


顺便说一下,您仍然应该std::forward 调用funcObj 时的参数,因为可能有一些右值引用需要进一步向下传播:

auto operator()(Args... args) 
{
return funcObj(std::forward<Args>(args)...);
}

关于c++ - 如何使用可变参数使模板推断函数的返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46401717/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com