【发布时间】:2021-06-08 23:06:48
【问题描述】:
在关于noexcept 异常规范的 C++ Primer 中,据说指向可能会隐式抛出的函数的指针(在没有异常规范的情况下定义,例如:void(*p)();)或显式(void(*p)() noexcept(false);)甚至可以指向任何函数到一个非抛出函数。
另一方面,可能不会抛出的函数指针(noexcept 例如void(*p) noexcept;)只能指向不会抛出的函数。
我发现这非常合乎逻辑,因为第一个指针可以从抛出函数指针指向非抛出函数,而第二个指针也很合乎逻辑。
我试过这个以了解更多:
void func1(){ // may throw
std::cout << "func1()\n";
}
void func2() noexcept(false){ // may throw
std::cout << "func2()\n";
}
void func3() noexcept(true){ // won't throw
std::cout << "func3()\n";
}
void func4() noexcept{ // won't throw
std::cout << "func4()\n";
}
int main(int argc, char* argv[]){
void(*pFn1)();
pFn1 = func1; // OK
pFn1 = func2; // OK
pFn1 = func3; // OK
pFn1 = func4; // OK
void(*pFn2)() noexcept(false);
pFn2 = func1; // OK
pFn2 = func2; // OK
pFn2 = func3; // OK
pFn2 = func4; // OK
void(*pFn3)() noexcept(true);
pFn3 = func1; // Error on C++ 17 and above. OK on C++11 and 14
pFn3 = func2; // Error on C++ 17 and above. OK on C++11 and 14
pFn3 = func3; // OK
pFn3 = func4; // OK
void(*pFn4)() noexcept(true);
pFn4 = func1; // Error on C++ 17 and above. OK on C++11 and 14
pFn4 = func2; // Error on C++ 17 and above. OK on C++11 and 14
pFn4 = func3; // OK
pFn4 = func4; // OK
std::cout << '\n';
}
- 当我针对
-std=c++17、-std=c++2a编译程序时,它可以正常工作,所以我得到了我在cmets 行中所写的错误。但是当我针对-std=c++11、-std=c++14进行编译时,它们都可以正常工作并且编译器不会抱怨?!
这是否意味着标准已经改变?谢谢!
【问题讨论】:
-
它可能在 C++14 及更低版本中未指定。然后有人注意到了差异,他们收紧了 C++17 的要求。
-
如果您知道您的报价来自标准的哪个部分,您可以将其与标准的先前版本进行比较,看看它是否存在。
-
看起来像一个 GCC 错误,Clang and MSVC reject it,根据cppreference,即使在 C++17 之前它也应该是一个错误。
-
看起来在C++14中,noexcept-ness不是函数类型的一部分,所以
pFn1、pFn2、pFn3和pFn4的声明都是除标识符外等价。 ([dcl.fct],尤其是第 1-2 段和第 6 段中的最后一个规范句)
标签: c++ function-pointers noexcept