我需要一种确定函数参数类型的方法,因此我编写了一个 closure_traits 类,如下所示,灵感来自 Is it possible to figure out the parameter type and return type of a lambda? .
但是,当我尝试将它应用到一个简单的 lambda 时,我收到“operator()”不是“(lambda type)”成员的错误。 然而,根据 cppreference,lambda 确实有一个 operator()。 我还尝试使用 std::function,并得到了等效的错误。 我想我不确定出了什么问题,我们将不胜感激任何帮助。
#include<type_traits>
#include<tuple>
#include<utility>
#include<iostream>
/* For generic types use the type signature of their operator() */
template <typename T>
struct closure_traits : public
closure_traits<decltype(&T::operator())> {};
/* Otherwise, we do a template match on a function type. */
template <typename ClassType, typename ReturnType,
typename... ArgTypes>
struct closure_traits<ReturnType (ClassType::*) (ArgTypes... args)>
{
using arity = std::integral_constant<std::size_t,
sizeof...(ArgTypes)>;
using Ret = ReturnType;
/* The argument types will be the same as the types of the
* elements of a tuple composed of them.
*/
template <std::size_t I>
struct Args {
using type = typename std::tuple_element<I,
std::tuple<ArgTypes...>>::type;
};
};
int main() {
auto thing = [=] (int x) {return x;};
std::cerr << "The number of arguments is "
<< closure_traits<decltype(thing)>::arity << std::endl;
return 0;
}
我收到的编译器错误消息如下。 我的编译命令只是 g++ -std=c++14 main.cpp。
main.cpp: In instantiation of ‘struct closure_traits<int (main()::<lambda(int)>::*)(int) const>’:
main.cpp:9:8: required from ‘struct closure_traits<main()::<lambda(int)> >’
main.cpp:34:82: required from here
main.cpp:9:56: error: ‘operator()’ is not a member of ‘int (main()::<lambda(int)>::*)(int) const’
struct closure_traits : public closure_traits<decltype(&T::operator())> {};
^
main.cpp: In function ‘int main()’:
main.cpp:34:51: error: ‘arity’ is not a member of ‘closure_traits<main()::<lambda(int)> >’
std::cerr << "The number of arguments is " << closure_traits<decltype(thing)>::arity << std::endl;
最佳答案
您的专业与 decltype(&T::operator())
不匹配争论。
正因为如此,编译器没有选择特化(如您所愿),而是被迫递归地选择相同的主模板。这使得它适用 &T::operator()
在已经应用一次之后再次表达。即最初尝试做 &T::operator()
实际上成功了,但随后编译器尝试应用 &T::operator()
再次,当T
已经是int (main()::<lambda(int)>::*)(int) const
.后者显然没有 operator ()
,这就是您收到此错误消息的原因。
无法选择您的专业的原因不明const
在模板参数声明中。 lambda 的 operator ()
实际上是一个 const
lambda 类的成员。添加const
到你的专业声明
template <typename ClassType, typename ReturnType,
typename... ArgTypes>
struct closure_traits<ReturnType (ClassType::*) (ArgTypes... args) const>
...
编译器将遵循您希望它遵循的特化路径。
当然,你必须打印 closure_traits<decltype(thing)>::arity::value
,不只是 closure_traits<decltype(thing)>::arity
.
关于C++ Lambda 没有 operator(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40411241/