摘要
由于某种原因,调用lambda函数的成员函数模板无法使用错误C2275编译...非法使用此类型作为表达式,但当函数移出时它正确编译的免费功能。
详情
首先,我有一个基类,可以将function
个实例保存在vector
中。只有派生类可以通过调用function
向vector
个add_external
实例添加function
个实例。可以通过调用invoke_externals
公开调用所有function
个实例。派生类将lambdas添加为invoke_internal
个实例。那些lambdas将依次用另一个“内部”lambda调用基类函数模板invoke_internal
。 invoke_internal
的模板参数是在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_;
};
中执行“内部”lambda时将被显式捕获的异常类型:
logic_error
然后我有两个琐碎的自由函数抛出runtime_error
和invoke_internal
例外。这些函数将用于void throws_logic_error()
{
throw logic_error("");
}
void throws_runtime_error()
{
throw runtime_error("");
}
:
derived
在add_external
类构造函数中,添加了两个lambdas invoke_internal
。每个lambdas都用“内部”lmbdas调用invoke_internal
。第一次调用logic_error
将明确捕获throws_logic_error
将抛出的invoke_internal
。对runtime_error
的第二次调用将明确捕获throws_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();
});
});
}
};
。
derived
要将所有这些组合在一起,invoke_externals
将被实例化,并调用derived
来调用int wmain(int, wchar_t*[])
{
derived().invoke_externals();
return 0;
}
构造函数中添加的“外部”lambdas。那些“外部”lambdas将反过来调用“内部”lambdas,并且将明确地捕获抛出的异常:
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
问题
但是,上面没有编译:
invoke_internal
...是针对derived
构造函数中invoke_internal
的调用而发出的。
如果我从base
移出base
并使其成为免费功能,则会进行编译。
问题
为什么我得到错误C2275 ...当函数模板是base
成员时,非法使用此类型作为表达式?
注意:将违规函数移出{{1}}并非最佳,因为在我的现实生活场景中,函数确实以不同的方式使用其类的状态。
答案 0 :(得分:5)
感谢@ 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(); }); });
} // ^^^^^^^^^^^^^^
不要问我为什么。一般来说,你得到的错误意味着,使用类型的模板没有被检测到。
通常这应该只发生在依赖类型/嵌套模板中,并且可以在问题模板之前直接用template
解决(如图所示),它告诉编译器一个模板跟着(duh)。我们之前需要this->
,因为否则它看起来像一个显式的实例化,这本身就是错误的:
template Foo<int>; // explicitly instantiate the Foo class template for int
现在。扼杀,这个问题也出现在这里,我只能同意@sehe这看起来像编译器的限制。
答案 1 :(得分:3)
这看起来像编译器限制。它使用--std = c ++ 0x
在gcc 4.6上编译正常如果有其他人想尝试,我做了一些工作来实际复制/过去这个正确的,编译,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;
}