如何解决奇怪的错误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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。