本文介绍了是否可以定义一个包含函数和lambda的可调用概念?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to define a concept that would accept all callable objects.Here's what I have done so far:

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;
}

但是,如果我定义了这些内容:

Yet if I define those:

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 )。

is_callable(g) is true but is_callable(f) is false, it did not work (I want both to return true).

所以我尝试查看以下内容是否编译:

So I tried to see if the following would compile:

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


$ b相同$ b

它给了我您可以在这4行注释中看到的错误。

It gave me the errors you can see as comment on those 4 lines.

是否有一种方法可以检查f是否具有有效的函子,这意味着f是lambda吗?

Is there a way to check is f has a valid functor which would mean f is a lambda?

对我要实现的目标是否有更好的解决方案?

Is there a better solution to what I am trying to achieve?

推荐答案

无法实现您想要的(或好的)

What you want is not possible (or a good idea, but nevermind that now).

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

A "function" by name in C++ represents potentially many functions. It represents overloads, template instantiations through template argument deduction, etc. But to get a function pointer, you are required to peer through all of that. If the name represents an overload set, to get a pointer, you have to cast that name to a specific overload. If the name represents a template, you have to provide the template arguments to denote a specific instantiation.

这意味着,当您假设的 is_callable 概念必须在函数指针类型上调用,所有重载解析和模板替换都已经发生。它只有一个指向特定的,定义明确的代码的指针,可以使用该指针的类型定义的签名来调用该代码。

What that means is that, by the time your hypothetical is_callable concept gets to be invoked on a function pointer type, all of the overload resolution and template substitution has already happened. It is given a single pointer to a specific, well-defined piece of code which can be called with a signature defined by the type of that pointer.

没有一个函数 object 的情况。函子(无论是由C ++ lambda表达式生成还是仅是手写类型)无非是带有 operator()重载的类型。而且,重载只是一个函数名,与其他名称完全一样:受重载解析和模板替换规则的约束。

None of that is the case for a function object. A functor (whether generated by a C++ lambda expression or just a hand-written type) is nothing more than a type with an operator() overload. And that overload is just a function name, exactly like any other name: subject to rules of overload resolution and template substitution.

C ++不允许您提出以下问题:这是一个名字;我可以用 something 来称呼它吗?

C++ does not allow you to ask the question "here's a name; can I call this with something?"

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

And broadly speaking, that's just not a useful question to ask.

无论您是使用这种可调用的概念进行交易还是什么,在某个时候,某些代码段都将使用某些函数来调用某些函数一组参数,最终将级联以使用由某个进程定义的另一组参数来调用给定函数。 这就是重点,当您需要约束给定的可调用对象时。

Whether you're using this "callable" concept for currying or whathaveyou, at some point, some piece of code is going to call some function with some set of arguments, which will eventually cascade into calling the given function with another set of argument defined by some process. That is the point when you need to constrain the given callable.

在构建咖喱可调用对象的站点上约束功能是无用。您不知道参数和返回值之间是否存在类型不匹配,或任何其他类型。您只有在获得一组用于调用curried可调用对象的参数时,才会知道这一点。在此处可以计算参数以最终调用适当的函数,因此应该在此处进行约束。

Constraining the function at the site where you're building the curried callable is useless. You have no idea if there's a type mismatch between arguments and return values, or anything of the kind. You will only know that when you're given a set of arguments to use to call the curried callable. That's the place when you can compute the arguments to eventually call the proper function, so that's where the constraining should happen.

这篇关于是否可以定义一个包含函数和lambda的可调用概念?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-06 09:47