【发布时间】:2021-06-05 09:42:14
【问题描述】:
std::function的构造函数没有声明noexcept:
template< class F > function( F f );
另一方面,C++ 参考提到以下内容:
如果 f 是函数指针或 std::reference_wrapper 则不抛出, 否则可能抛出 std::bad_alloc 或副本抛出的任何异常 存储的可调用对象的构造函数。
这是否意味着可以安全地声明以下类的构造函数noexcept,因为我使用指向静态成员函数的指针初始化std::function?
class Worker
{
public:
Worker() noexcept {} // ok?
void test() { reporter("test"); }
private:
static void dummy(const std::string& ) {};
std::function<void (const std::string&)> reporter = &dummy; // doesn't throw an exception?
};
int main()
{
Worker w;
w.test();
}
如果 std::function 成员是从 lambda 构造的,那么声明构造函数 noexcept 会出错吗?
class Worker
{
public:
Worker() noexcept {} // bad?
void test() { reporter("Test"); }
private:
std::function<void (const std::string&)> reporter = [](const std::string& ){}; // may throw?
};
我还注意到,当声明 noexcept 的构造函数默认时,GCC 会出错,因为它的异常规范与隐式异常规范不匹配,即 noexcept(false) 由于 std::function 构造函数未声明为 noexcept。
class Worker
{
public:
Worker() noexcept = default; // this won't compile
void test() { reporter("test"); }
private:
static void dummy(const std::string& ) {};
std::function<void (const std::string&)> reporter = &dummy;
};
【问题讨论】:
-
我相信您的两个问题的答案都是“是”。由于
std::function的构造函数没有声明noexcept,编译器无法自动检测到构造函数不能抛出,只是在标准的散文中描述为有时不抛出。我想可能有可能提供std::function构造函数的几个重载,使用 SFINAE 技术将那些可以标记为noexcept的部分与那些不能标记的部分分开,但无论好坏,标准都不需要这样做。