C++ Lambda没有operator()

san*_*rey 9 c++ lambda templates functional-programming c++14

我需要一种方法来计算函数的参数类型,所以我编写了一个closure_traits类,如下所示,受到启发是否有可能找出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;                                                                                                                       
}    
Run Code Online (Sandbox Code Playgroud)

我得到的编译器错误消息如下.我的编译命令只是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; 
Run Code Online (Sandbox Code Playgroud)

AnT*_*AnT 9

您的专业化与decltype(&T::operator())参数不符.

因此,编译器不是选择专门化(如您所愿),而是强制以递归方式选择相同的主模板.这使得它&T::operator()在已经应用一次之后再次应用表达式.即初始尝试&T::operator()实际上成功,但编译器尝试&T::operator()再次应用,何时T已经int (main()::<lambda(int)>::*)(int) const.显然,后者没有operator (),这就是你收到此错误消息的原因.

const模板参数声明中缺少无法选择专业化的原因.lambda operator ()实际上是constlambda类的成员.添加const到您的专业化声明

template <typename ClassType, typename ReturnType, 
          typename... ArgTypes>                                                  
struct closure_traits<ReturnType (ClassType::*) (ArgTypes... args) const>   
...
Run Code Online (Sandbox Code Playgroud)

编译器将遵循您希望它遵循的特化路径.

而且,当然,你必须打印closure_traits<decltype(thing)>::arity::value,而不仅仅是closure_traits<decltype(thing)>::arity.