C++ Lambda 没有 operator()

标签 c++ templates lambda functional-programming c++14

我需要一种确定函数参数类型的方法,因此我编写了一个 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/

相关文章:

c++ - 删除元素后,(c++) vector 会缩小吗?

c++ - 在 C++ 方法中创建模板类?

python - 使用 operator.itemgetter() 作为排序键时,有没有办法转换值?

c++ - sys/types.h 和 linux/types.h 的冲突重新声明

c++ - 在 std::string 中使用自定义分配器重新使用已分配的 char 缓冲区

c++ - 当我们将特定类型传递给类模板时生成类

c++ - 使用 gcc 但使用 Clang 时没有关于模板函数中未使用参数的警告

C++模板代码解释

spring - 了解实例变量名称和使用 Spring @Bean 注解创建它的方法

c++ - C++11 lambda 捕获实际捕获了多少?