奇怪的错误 C2275 ..非法使用此类型作为成员函数模板和 lambda 的表达式
Strange error C2275 ... illegal use of this type as an expression with member function template and lambdas
摘要
由于某种原因,调用 lambda 函数的成员函数模板无法编译并显示错误 C2275 ...非法使用此类型作为表达式,但是当函数被移出为自由函数时,它会正确编译。
详
首先,我有一个基类,可以将function
实例保存在vector
中。只有派生类才能通过调用add_external
function
实例添加到该vector
。所有function
实例都可以通过调用 invoke_externals
来公开调用。派生类会将 lambda 添加为function
实例。这些 lambda 将依次调用基类函数模板,invoke_internal
另一个"内部"lambda。要invoke_internal
的模板参数是一种异常类型,在invoke_internal
中执行"内部"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
类构造函数中,添加了两个带有 add_external
的 lambda。这些 lambda 中的每一个都用"内部"lmbda 调用invoke_internal
。对invoke_internal
的第一个调用将显式捕获throws_logic_error
将抛出的logic_error
。对invoke_internal
的第二次调用将显式捕获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();
});
});
}
};
为了将所有这些联系在一起,derived
被实例化并调用invoke_externals
来调用derived
构造函数中添加的"外部"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
的调用发出。
如果我invoke_internal
从base
中移出并使其成为自由函数,那么它就会编译。
问题
为什么我收到错误 C2275 ...当函数模板是base
成员时,非法使用此类型作为表达式?
注意:将有问题的函数移出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(); }); });
} // ^^^^^^^^^^^^^^
不要问我为什么。通常,您收到的错误意味着未检测到使用该类型的模板。
通常,这应该只发生在依赖类型/嵌套模板中,并且可以通过直接在相关模板之前使用template
来解决(如图所示(,它告诉编译器模板遵循(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;
}
- 是否可以获取成员函数模板参数的拥有对象?
- 实例化多种类型的成员函数模板
- C++:递归成员函数模板
- C++成员函数模板将成员函数指针作为模板参数
- 类和成员函数模板专用化出错
- 调用类模板的成员函数模板
- 课堂中成员函数模板的明确实例
- 专用和/或重载具有可变参数的成员函数模板
- 具有可变参数的类成员函数模板部分专用化
- 将 PIMPL 习惯用法与成员函数模板一起使用(无需预先了解所有可能的数据类型)
- 澄清了使用 enable_if 的成员函数模板专用化
- 是否可以从指向成员函数模板参数的指针推断类类型
- 成员函数模板推演指南或其他方法让编译器知道如何调用函数
- 成员函数模板不会在 clang 上编译,但在 GCC 上编译
- 类模板的成员函数模板找不到定义,尽管存在显式实例化。不链接
- 成员函数模板参数的部分专业化
- 在C++中创建成员函数模板专用化
- 要求派生类提供成员函数模板
- 实例化错误后成员函数模板的专业化,以及成员函数的顺序
- 使用提升::函数的成员函数模板