首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以定义一个包含函数和lambda的可调用概念?

是否可以定义一个包含函数和lambda的可调用概念?
EN

Stack Overflow用户
提问于 2020-05-07 01:50:45
回答 1查看 330关注 0票数 1

我想定义一个接受所有可调用对象的概念。以下是我到目前为止所做的工作:

代码语言:javascript
复制
template<typename F>
concept Func = std::is_function_v<std::remove_pointer_t<std::decay_t<F>>> || (requires (F f) {
    std::is_function_v<decltype(f.operator())>;
});

bool is_callable(Func auto&&) {
    return true;
}

bool is_callable(auto&&) {
    return false;
}

然而,如果我定义这些:

代码语言:javascript
复制
auto f = [](auto a, auto b, auto c, auto d, auto e) {
    return a * b * c * d * e;
};

int g(int a, int b) {
    return a + b;
}

is_callable(g)true,但is_callable(f)false,它不起作用(我希望两者都返回true)。

所以我试着看看下面的代码是否可以编译:

代码语言:javascript
复制
decltype(f.operator()) // Reference to non-static member function must be called
decltype(&f.operator()) // Cannot create a non-constant pointer to member function
decltype(f::operator()) // 'f' is not a class, namespace, or enumeration
decltype(&f::operator()) // same as previously

它给出了你可以在这4行代码上看到的错误。

有没有办法检查f是否有一个有效的函数器,这意味着f是一个lambda?

对于我正在尝试实现的目标,有没有更好的解决方案?

EN

回答 1

Stack Overflow用户

发布于 2020-05-07 02:57:15

你想要什么是不可能的(或者是一个好主意,但现在别管它了)。

在C++中,一个名称为"function“的函数可能代表许多函数。它表示重载、通过模板参数推导的模板实例化等。但要获得函数指针,您需要仔细查看所有这些内容。如果名称表示重载集,则要获取指针,必须将该名称强制转换为特定的重载。如果名称表示模板,则必须提供模板参数来表示特定的实例化。

这意味着,当您假设的is_callable概念在函数指针类型上被调用时,所有的重载解析和模板替换都已经发生。它被赋予一个指向特定的、定义良好的代码段的指针,可以用该指针的类型定义的签名来调用该代码段。

所有这些都不是函数对象的情况。函数器(无论是由C++λ表达式生成的,还是仅由手写类型生成的)只不过是一个带有operator()重载的类型。该重载只是一个函数名,与任何其他名称完全相同:受重载解析和模板替换规则的约束。

C++不允许您提出这样的问题:“这是一个名称;我可以用一些东西来调用它吗?”

从广义上讲,这不是一个有用的问题。

无论你是在使用这个“可调用”的概念来进行调用,还是在某个时刻,某段代码将使用某组参数调用某个函数,这最终会级联到使用某个进程定义的另一组参数调用给定的函数。这就是当你需要约束给定的可调用对象的时候。

在构建curried的地方约束函数是没有用的。你不知道参数和返回值之间是否存在类型不匹配,或者类似的东西。只有当给出一组用于调用curried可调用的参数时,您才会知道这一点。这是您可以计算参数以最终调用适当函数的地方,因此这是约束应该发生的地方。

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

https://stackoverflow.com/questions/61641848

复制
相关文章

相似问题

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