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.