C++ 在嵌套lambda中应用函数_traits时编译失败

C++ 在嵌套lambda中应用函数_traits时编译失败,c++,templates,visual-c++,lambda,C++,Templates,Visual C++,Lambda,首先,我有一个类似这样的东西,一个重命名的函数,用于获取lambda的返回类型 template <typename T> struct FuncAnalyzer { }; template <typename T, typename TRet, typename... TArgs> struct FuncAnalyzer<TRet(T::*)(TArgs...) const> { using TReturn = TRet; }; template

首先,我有一个类似这样的东西,一个重命名的函数,用于获取lambda的返回类型

template <typename T>
struct FuncAnalyzer
{
};

template <typename T, typename TRet, typename... TArgs>
struct FuncAnalyzer<TRet(T::*)(TArgs...) const>
{
    using TReturn = TRet;
};

template <typename T>
struct FunctionAnalyzer
    : public FuncAnalyzer<decltype(&T::operator())>
{
};
模板
结构函数分析器
{
};
模板
结构函数分析器
{
使用TReturn=TRet;
};
模板
结构函数分析器
:公共函数分析器
{
};
然后当我在一个方法中有这个时,compi:

auto a = [](const int& key) -> QString { return QString::number(key); };
using b = FunctionAnalyzer<decltype(a)>::TReturn;
b x;
autoa=[](const int&key)->QString{return QString::number(key);};
使用b=Functionalyzer::TReturn;
bx;
但是当我试着把它放在一个lambda里时,它不起作用

    auto c = [](const int& key) -> QString 
    { 
        auto a = [](const int& key) -> QString { return QString::number(key); };
        using b = FunctionAnalyzer<decltype(a)>::TReturn;
        b x;
        return QString::number(key); 
    };
autoc=[](常量int&key)->QString
{ 
自动a=[](常量int&key)->QString{return QString::number(key);};
使用b=Functionalyzer::TReturn;
bx;
返回QString::number(键);
};
汇编输出:

1>i:\uicgraph\common\FunctionAnalyzer.h(21): error C2825: 'T': must be a class or namespace when followed by '::'
1>          Controller\Schema\SchemaController.cpp(105) : see reference to class template instantiation 'ValidSig::FunctionAnalyzer<QString (__cdecl *)(const int &)>' being compiled
1>i:\uicgraph\common\FunctionAnalyzer.h(21): error C2039: '()' : is not a member of '`global namespace''
1>i:\uicgraph\common\FunctionAnalyzer.h(21): error C2275: 'T' : illegal use of this type as an expression
1>          Controller\Schema\SchemaController.cpp(105) : see declaration of 'T'
1>          Controller\Schema\SchemaController.cpp(105) : see declaration of 'T'
1>i:\uicgraph\common\FunctionAnalyzer.h(21): error C2146: syntax error : missing ')' before identifier '()'
1>i:\uicgraph\common\FunctionAnalyzer.h(21): error C2143: syntax error : missing ',' before ')'
1>i:\uicgraph\common\FunctionAnalyzer.h(21): error C2947: expecting '>' to terminate template-argument-list, found '>'
1>Controller\Schema\SchemaController.cpp(105): error C2039: 'TReturn' : is not a member of 'ValidSig::FunctionAnalyzer<QString (__cdecl *)(const int &)>'
1>Controller\Schema\SchemaController.cpp(105): error C2061: syntax error : identifier 'TReturn'
1>i:\uicgraph\common\functionalyzer.h(21):错误C2825:“T”:后跟“:”时必须是类或命名空间
1> Controller\Schema\SchemaController.cpp(105):请参阅对正在编译的类模板实例化“ValidSig::Functionalyzer”的引用
1> i:\uicgraph\common\functionalyzer.h(21):错误C2039:“()”:不是“全局命名空间”的成员
1> i:\uicgraph\common\functionalyzer.h(21):错误C2275:“T”:非法使用此类型作为表达式
1> Controller\Schema\SchemaController.cpp(105):请参见“T”的声明
1> Controller\Schema\SchemaController.cpp(105):请参见“T”的声明
1> i:\uicgraph\common\functionalyzer.h(21):错误C2146:语法错误:标识符“()”之前缺少“')”
1> i:\uicgraph\common\functionalyzer.h(21):错误C2143:语法错误:缺少“,”before“,”
1> i:\uicgraph\common\functionalyzer.h(21):错误C2947:期望'>'终止模板参数列表,找到'>'
1> Controller\Schema\SchemaController.cpp(105):错误C2039:“TReturn”:不是“ValidSig::Functionalyzer”的成员
1> Controller\Schema\SchemaController.cpp(105):错误C2061:语法错误:标识符“TReturn”

我正在使用MSVC 2013

我们可以将示例简化为

template <class T> struct identity {using type = T;};

template <typename T>
struct FunctionAnalyzer
    : identity<decltype(&T::operator())> {};

int main()
{
    []
    {
        auto a = []{};
        using b = FunctionAnalyzer<decltype(a)>::type;
    }();
}
就在lambda内部的线之前。除了说它不正确之外,我真的无法解释这种行为,因为很明显,类类型不是指向函数类型的指针。错误报告应该是适当的

解决方法是在外部定义lambda

auto a = []{};
[a] // This is not required by standard! VC++ being stupid I guess
{
    using b = FunctionAnalyzer<decltype(a)>::type;
}();
autoa=[]{};
[a] //这不是标准要求的!我想VC++是愚蠢的
{
使用b=Functionalyzer::type;
}();

.

好,重写模板后问题已解决

template <typename TFunc>
struct FunctionAnalyzer
{
    using ReturnType = typename FunctionAnalyzer<decltype(&TFunc::operator())>::ReturnType;
};

template <typename TClass, typename TRet, typename... TArgs>
struct FunctionAnalyzer<TRet(TClass::*)(TArgs...) const>
{
    using ReturnType = TRet;
};

template <typename TRet, typename... TArgs>
struct FunctionAnalyzer<TRet(*)(TArgs...)>
{
    using ReturnType = TRet;
};
模板
结构函数分析器
{
使用ReturnType=typename Functionalyzer::ReturnType;
};
模板
结构函数分析器
{
使用ReturnType=TRet;
};
模板
结构函数分析器
{
使用ReturnType=TRet;
};

这似乎是VS2013的问题。如果去掉函数指针的第三个模板,它就不起作用了。

我尝试了你的代码(将QString改为int,因为我没有安装Qt),它似乎在g++和clang++中工作,请看,这似乎是一个VC问题,因为每当你将编译器改为VC++时都会出现错误谢谢,我会报告这一点。有没有绕过这个问题的解决方案?进一步简化:
int main(){[]{[]{}.operator();};}
gcc和clang仍然接受这一点,但在MSVC上失败,出现“错误C2228:left of.”(“()”必须有class/struct/union”@hvd哦,是的。我认为问题是我们试图从实际上下文之外的模板中访问成员。我也遇到了同样的问题,现在它开始工作了!谢谢你的解决方案。
template <typename TFunc>
struct FunctionAnalyzer
{
    using ReturnType = typename FunctionAnalyzer<decltype(&TFunc::operator())>::ReturnType;
};

template <typename TClass, typename TRet, typename... TArgs>
struct FunctionAnalyzer<TRet(TClass::*)(TArgs...) const>
{
    using ReturnType = TRet;
};

template <typename TRet, typename... TArgs>
struct FunctionAnalyzer<TRet(*)(TArgs...)>
{
    using ReturnType = TRet;
};