奇怪的错误C2275…非法使用这种类型作为成员函数模板和lambda的表达式

问题描述

| 摘要 由于某种原因,我调用lambda函数的成员函数模板无法编译,错误代码为C2275 ...非法将该类型用作表达式,但是当该函数移出为自由函数时,它将正确编译。 细节 首先,我有一个基类,将
function
实例保存在
vector
中。只有派生类可以通过调用
add_external
function
实例添加到
vector
中。所有的“ 0”实例都可以通过调用“ 6”来公开调用。派生类会将lambda添加为“ 0”实例。这些lambda会依次调用基类函数模板
invoke_internal
和另一个\“ inner \” lambda。
invoke_internal
的模板参数是一个异常类型,在
invoke_internal
中执行\“ inner \” lambda时将明确捕获该异常类型:
using namespace std;

class base
{
public:
    void invoke_externals()
    {
        for (auto it = funcs_.begin(); it != funcs_.end(); ++it)
        {
            (*it)();
        }
    }

protected:
    void add_external(function<void(void)> func)
    {
        funcs_.push_back(func);
    }

    template <typename T>
    void invoke_internal(function<void(void)> func)
    {
        try
        {
            func();
        }
        catch (const T&){}
        catch (...){}
    }

    vector<function<void(void)>> funcs_;
};
然后,我有两个琐碎的自由函数,它们抛出
logic_error
runtime_error
异常。这些函数将在
invoke_internal
中调用的“内部” lambda中使用:
void throws_logic_error()
{
    throw logic_error(\"\");
}

void throws_runtime_error()
{
    throw runtime_error(\"\");
}
derived
类构造函数中,两个lambda与
add_external
相加。这些lambda中的每一个都以“ inner” lambdas称为“ 8”。对call8ѭ的第一次调用将明确捕获
throws_logic_error
将抛出的ѭ12.。对call8ѭ的第二次调用将明确捕获
throws_runtime_error
将抛出的
runtime_error
class derived : public base
{
public:
    derived()
    {
        add_external([this]()
        {
            invoke_internal<logic_error>([]()
            {
                throws_logic_error();
            });
        });

        add_external([this]()
        {
            invoke_internal<runtime_error>([]()
            {
                throws_runtime_error();
            }); 
        });
    }
};
为了将所有这些联系在一起,实例化了16并调用了6来调用在16构造函数中添加的“外部” lambda。那些“外部” lambda将依次调用“内部” lambda,并且抛出的异常将被明确捕获:
int wmain(int,wchar_t*[])
{
    derived().invoke_externals();

    return 0;
}
问题 但是,以上代码无法编译:
error C2275: \'std::logic_error\' : illegal use of this type as an expression
error C2275: \'std::runtime_error\' : illegal use of this type as an expression
...被发出以调用
derived
构造函数中的
invoke_internal
。 如果我将ѭ8from从
base
中移出并使其成为自由函数,则它将进行编译。 题 当函数模板是
base
成员时,为什么会收到错误C2275 ...非法使用此类型作为表达式? 注意:将有问题的功能移出
base
并不是最佳选择,因为在我的实际场景中,该功能实际上以不同的方式使用其类状态。     

解决方法

        感谢@sehe \的回答,我可以在VS2010上对此进行测试。以下代码有效:
derived()
{   //                       vvvvvvvvvvvvvv
    add_external([this] () { this->template invoke_internal<logic_error>([]() { throws_logic_error(); }); });

    add_external([this] () { this->template invoke_internal<runtime_error>([]() { throws_runtime_error(); }); });
}   //                       ^^^^^^^^^^^^^^
不要问我为什么。通常,您得到的错误意味着,未检测到使用该类型的模板。 通常,这仅应在相关类型/嵌套模板中发生,并且可以在有问题的模板之前直接用ѭ38来解决(如图所示),这告诉编译器紧随其后的模板(duh)。但是在此之前我们需要
this->
,因为否则它看起来像是一个显式实例化,它本身是错误的:
template Foo<int>; // explicitly instantiate the Foo class template for int
现在。奇怪的是,此问题也在这里发生,我只能同意@sehe,这看起来像是编译器的限制。     ,        这看起来像是编译器的限制。它在gcc 4.6上使用--std = c ++ 0x可以正常编译 万一其他人想尝试,我做了一些工作,将其实际复制/粘贴到适当的,编译的TU中:
#include <vector>
#include <functional>
#include <stdexcept>
using namespace std;

class base
{
    public:

        void invoke_externals()
        {
            for (auto it = funcs_.begin(); it != funcs_.end(); ++it)
            {
                (*it)();
            }
        }

    protected:

        void add_external(function<void(void)> func)
        {
            funcs_.push_back(func);
        }

        template <typename T>
            void invoke_internal(function<void(void)> func)
            {
                try
                {
                    func();
                }
                catch (const T&)
                {
                }
                catch (...)
                {
                }
            }

        vector<function<void(void)>> funcs_;
};

void throws_logic_error()   { throw logic_error(\"\");   }
void throws_runtime_error() { throw runtime_error(\"\"); }

class derived : public base
{
    public:

        derived()
        {
            add_external([this] () { invoke_internal<logic_error>([]() { throws_logic_error(); }); });

            auto g = [this] () { invoke_internal<runtime_error>([]() { throws_runtime_error(); }); };
            add_external(g);
        }
};

int main(int,char*[])
{
    derived().invoke_externals();

    return 0;
}
    

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...