C++ 由函数指针初始化的std::函数的异常安全性
未声明C++ 由函数指针初始化的std::函数的异常安全性,c++,c++17,C++,C++17,未声明std::function的构造函数noexcept: 模板函数(F); 另一方面,C++引用提到以下内容: 如果f是函数指针或std::reference_包装器,则不会抛出, 否则可能会抛出std::bad_alloc或副本引发的任何异常 存储的可调用对象的构造函数 这是否意味着可以安全地声明以下类的构造函数noexcept,因为我使用指向静态成员函数的指针初始化std::function 类工作者 { 公众: Worker()没有异常{}//可以吗? void test(){rep
std::function
的构造函数noexcept
:
模板函数(F);
另一方面,C++引用提到以下内容:
如果f是函数指针或std::reference_包装器,则不会抛出,
否则可能会抛出std::bad_alloc或副本引发的任何异常
存储的可调用对象的构造函数
这是否意味着可以安全地声明以下类的构造函数noexcept
,因为我使用指向静态成员函数的指针初始化std::function
类工作者
{
公众:
Worker()没有异常{}//可以吗?
void test(){reporter(“test”);}
私人:
静态空虚拟(const std::string&){};
std::function reporter=&dummy;//是否不引发异常?
};
int main()
{
工人w;
w、 test();
}
如果std::function
成员是从lambda构造的,那么声明构造函数noexcept
将是错误的
类工作者
{
公众:
Worker()无异常{}//错误?
void test(){reporter(“test”);}
私人:
std::function reporter=[](const std::string&){};//可以抛出吗?
};
我还注意到,当构造函数声明为noexcept
时,GCC会给出一个错误,因为它的异常规范与隐式异常规范不匹配,隐式异常规范是noexcept(false)
,因为std::function
构造函数未声明为noexcept
类工作者
{
公众:
Worker()noexcept=default;//这不会编译
void test(){reporter(“test”);}
私人:
静态空虚拟(const std::string&){};
std::function reporter=&dummy;
};
这是否意味着可以安全地声明以下类的构造函数noexcept
,因为我使用指向静态成员函数的指针初始化std::function
请注意,声明函数noexcept
总是“安全的”。如果抛出异常,程序将终止,但这不是未定义的行为
但是是的,在您的情况下,不应该抛出任何异常,因此不应该终止程序。标准说:“如果f
是函数指针,则不会抛出任何内容。”
如果std::function
成员是从lambda构造的,那么声明构造函数noexcept
将是错误的
是的,它在您想要的意义上是“错误的”(如果抛出,程序将终止),因为lambda不是函数指针。相反,在lambda前面加上一元运算符+
,使其成为函数指针:
std::function<void (const std::string&)> reporter = +[](const std::string& ){};
std::function reporter=+[](const std::string&){};
我可能会在评论中提到这一点,特别是如果您没有评论为什么构造函数是noexcept
我还注意到,当构造函数声明的noexcept
为默认值时,GCC会给出一个错误
GCC和Clang的最新版本都没有给出错误,因此如果这是真的,则可能是标准中发布的缺陷报告。我相信您的两个问题的答案都是“是”。编译器无法自动检测到构造函数不能抛出,因为
std::function
的构造函数没有声明noexcept
,在标准的散文中它只是被描述为有时不抛出。我想有可能提供几个std::function
构造函数的重载,使用SFINAE技术将那些可以标记为noexcept
的构造函数与那些不能标记的构造函数分开,但不管是好是坏,该标准并不要求这样做。noexcept
和default
之间的交互作用在中已修复(追溯)。非常感谢您的参考!这似乎是其中之一,是的。