首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在c++17中传递与std::invoke一起使用的可调用对象

问如何在c++17中传递与std::invoke一起使用的可调用对象
EN

Stack Overflow用户
提问于 2020-01-14 23:09:13
回答 2查看 150关注 0票数 4

为什么在将i传递给构造函数时以下代码不能编译。其他类似的构造会被编译。

代码语言:javascript
复制
#include <iostream>
#include <functional>

int RetXPrintU(int x, uint u)
{
    std::cout << "RetXprintU(): " << u << std::endl;
    return x;
}

template <typename Fn, typename... Args>
void Call(Fn&& fun, Args&&... args)
{
    std::invoke(std::forward<Fn>(fun), std::forward<Args>(args)...);
}

template <typename Fn, typename... Args>
class CallableObj
{
public:
    explicit CallableObj(Fn&& fun, Args&&... args)
    {
        std::invoke(std::forward<Fn>(fun), std::forward<Args>(args)...);
    }
};

int main() {
    int i = 4;
    std::invoke(RetXPrintU, i, 8u);
    Call(RetXPrintU, i, 8u);
    CallableObj co(RetXPrintU, i, 8u); // WHY I DO NOT COMPILE?
    //CallableObj co(RetXPrintU, 0, 8u); // WHY I COMPILE?

    return 0;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-14 23:18:21

正如错误消息所说,编译器无法推导出CallableObj的模板参数。为此,您需要添加一个扣减指南:

代码语言:javascript
复制
template <typename Fn, typename... Args>
CallableObj(Fn&& fun, Args&&... args) -> CallableObj<Fn, Args>...>;

整个代码是这样写的:

代码语言:javascript
复制
template <typename Fn, typename... Args>
class CallableObj
{
public:
    explicit CallableObj(Fn fun, Args... args)
    {
        std::invoke(std::forward<Fn>(fun), std::forward<Args>(args)...);
    }
};

template <typename Fn, typename... Args>
CallableObj(Fn&& fun, Args&&... args) -> CallableObj<Fn, Args...>;

正如@Jarod42指出的那样,没有必要让构造函数本身成为模板(就像在答案的第一个版本中一样)。

这是一个live example (由@jarod42修正的版本)。

我假设您的代码只是一个最小的示例,并且您需要将类作为模板。如果不是这样,你最好使用另一种解决方案。

票数 3
EN

Stack Overflow用户

发布于 2020-01-14 23:18:36

这里的问题是您需要将模板从类移动到构造器。当你有了

代码语言:javascript
复制
template <typename Fn, typename... Args>
class CallableObj
{
public:
    explicit CallableObj(Fn&& fun, Args&&... args)
    {
        std::invoke(std::forward<Fn>(fun), std::forward<Args>(args)...);
    }
};

Args&&...不是可变转发引用,因为它是为类本身推导的,并且当您调用CallableObj co(RetXPrintU, i, 8u);时,类被实例化,构造函数被标记为

代码语言:javascript
复制
explicit CallableObj(int(int, unsigned int)&& fun, int&& arg1, unsigned int&& arg2)

我们想要的是

代码语言:javascript
复制
class CallableObj
{
public:
    template <typename Fn, typename... Args>
    explicit CallableObj(Fn&& fun, Args&&... args)
    {
        std::invoke(std::forward<Fn>(fun), std::forward<Args>(args)...);
    }
};

因此,现在当构造函数被调用时,Args将被推导出来,而Args&&现在是一个转发引用。

CallableObj co(RetXPrintU, 0, 8u);在你的例子中工作的原因是因为0是一个prvalue,并且prvalue可以绑定到一个rvalue引用。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59736558

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档