奇怪的错误C2275 ...非法使用此类型作为一个表达式与成员函数模板和lambdas [英] Strange error C2275 ... illegal use of this type as an expression with member function template and lambdas
问题描述
摘要
由于某种原因,调用lambda函数的成员函数模板无法使用错误C2275编译。非法使用此类型作为表达式,但是当函数被移出是一个自由函数时,它会正确编译。
/ strong>
首先,我有一个基类,在向量中保留
。只有派生类可以通过调用 function
add_external $ c $>向
向量
添加 function
c>。所有 function
实例可以通过调用 invoke_externals
来公开调用。派生类将添加lambdas作为 function
实例。那些lambdas将依次调用基类类函数模板 invoke_internal
与另一个内部lambda。 invoke_internal
中的模板参数是在 invoke_internal
中执行内部lambda时将被显式捕获的异常类型:
using namespace std;
class base
{
public:
void invoke_externals()
{
for(auto it = funcs_.begin != 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 >> funcs_;
};
然后我有两个琐碎的自由函数,引发 logic_error
和 runtime_error
异常。这些函数用于 invoke_internal
中调用的内部lambda:
void throws_logic_error()
{
throw logic_error();
}
void throws_runtime_error()
{
throw runtime_error();
}
<类构造函数,两个lambdas添加 add_external
。每个这些lambdas调用 invoke_internal
与innerlmbdas。第一次调用 invoke_internal
将显式捕获 logic_error
throws_logic_error
会抛出。第二次调用 invoke_internal
将显式捕获 runtime_error
, throws_runtime_error
将抛出。
类派生:public base
{
public:
derived )
{
add_external([this]()
{
invoke_internal< logic_error>([]()
{
throws_logic_error $ b});
});
add_external([this]()
{
invoke_internal< runtime_error>([]()
{
throws_runtime_error();
});
});
}
};
将所有这些结合在一起,派生
实例化并调用 invoke_externals
以调用在派生
构造函数中添加的externallambdas。这些外部lambda将反过来调用内部lambdas和抛出的异常将被明确捕获:
int wmain int,wchar_t * [])
{
derived()。invoke_externals();
return 0;
}
问题
但是,以上不编译:
错误C2275:'std :: logic_error':非法使用此类型作为表达式
错误C2275:'std :: runtime_error':非法使用此类型作为表达式
$ b在派生
构造函数中对 invoke_internal
的调用发出
$ b <
如果我从 base
移动 invoke_internal
它是一个自由功能,然后它编译。</ p>
问题
当函数模板是 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();});});
} // ^^^^^^^^^^^^^
不要问我为什么。一般来说,你得到的错误意味着,没有检测到使用类型的模板。
通常这只应该出现在依赖类型/嵌套模板中,并且可以使用模板
直接解决问题的模板(如图所示)模板(duh)。我们需要 this->
之前,因为否则它看起来像一个显式的实例化,这本身是错误的:
template Foo< int> ;; //显式实例化int类的Foo类模板
现在。奇怪,这个问题也发生在这里,我只能同意@sehe,这看起来像一个编译器的限制。
Summary
For some reason, my member function template that invokes a lambda function fails to compile with error C2275 ... illegal use of this type as an expression, but when the function is moved out to be a free function it compiles correctly.
Details
First I have a base class that keeps function
instances in a vector
. Only derived classes can add function
instances to that vector
by calling add_external
. All function
instances can be publicly invoked by calling invoke_externals
. A derived class will add lambdas as function
instances. Those lambdas will in turn call the base class function template invoke_internal
with another "inner" lambda. The template parameter to invoke_internal
is an exception type that will be explicitly caught when executing the "inner" lambda in 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_;
};
Then I have two trivial free functions that throws logic_error
and runtime_error
exceptions. These functions are to be used in the "inner" lambda that is invoked in invoke_internal
:
void throws_logic_error()
{
throw logic_error("");
}
void throws_runtime_error()
{
throw runtime_error("");
}
In the derived
class constructor, two lambdas are added with add_external
. Each of those lambdas call invoke_internal
with "inner" lmbdas. The first call to invoke_internal
will explicitly catch the logic_error
that throws_logic_error
will throw. The second call to invoke_internal
will explicitly catch the runtime_error
that throws_runtime_error
will throw.
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();
});
});
}
};
And to tie all this together, derived
is instantiated and invoke_externals
is called to invoke the "external" lambdas added in the derived
constructor. Those "external" lambdas will in turn invoke the "inner" lambdas and the thrown exceptions will be explicitly caught:
int wmain(int, wchar_t*[])
{
derived().invoke_externals();
return 0;
}
Problem
However, the above don't compile:
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
...is issued for the calls to invoke_internal
in the derived
constructor.
If I move invoke_internal
out from base
and make it a free function, then it compiles.
Question
Why do I get error C2275 ... illegal use of this type as an expression when the function template is a base
member?
Note: Moving the offending function out of base
isn't optimal since in my real life scenario the function actually do use its class' state in different ways.
Thanks to @sehe's answer, I could test this myself on VS2010. The following code works:
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(); }); });
} // ^^^^^^^^^^^^^^
Don't ask me why.Generally, the error that you get means, that the template, where the type was used, was not detected as such.
Normally this should only occur with dependent types / nested templates and can be solved with a template
directly before the template in question (as shown), which tells the compiler that a template follows (duh). We need this->
before that though, because else it would look like an explicit instantiation, which would be wrong on its own:
template Foo<int>; // explicitly instantiate the Foo class template for int
Now. strangly, this problem also occurs here and I can only agree with @sehe that this looks like a compiler limitation.
这篇关于奇怪的错误C2275 ...非法使用此类型作为一个表达式与成员函数模板和lambdas的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!