std::throw_with_nested期望c++ 11中的多态类型

std::throw_with_nested expects polymorphic type in C++11?

本文关键字:多态 类型 期望 throw with nested std c++      更新时间:2023-10-16

为什么不能编译(在Clang 3.4.2和GCC 4.7.4, 4.8.3和4.9.1版本中尝试过):

#include <exception>
struct E { E(int) {} };
int main() {
  std::throw_with_nested(E(42));
  return 0;
}

GCC 4.9.1错误:

In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/exception:163:0,
                from test.cpp:1:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/bits/nested_exception.h: In instantiation of 'static const std::nested_exception* std::__get_nested_helper<_Ex>::_S_get(const _Ex&) [with _Ex = E]':
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/bits/nested_exception.h:104:51:   required from 'const std::nested_exception* std::__get_nested_exception(const _Ex&) [with _Ex = E]'
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/bits/nested_exception.h:138:38:   required from 'void std::throw_with_nested(_Ex) [with _Ex = E]'
test.cpp:6:31:   required from here
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/bits/nested_exception.h:90:59: error: cannot dynamic_cast '& __ex' (of type 'const struct E*') to type 'const class std::nested_exception*' (source type is not polymorphic)
      { return dynamic_cast<const nested_exception*>(&__ex); }
                                                          ^

Clang 3.4.2:

In file included from test.cpp:1:
In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/exception:163:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/bits/nested_exception.h:90:16: error: 'E' is not polymorphic
      { return dynamic_cast<const nested_exception*>(&__ex); }
              ^                                     ~~~~~
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/bits/nested_exception.h:104:40: note: in instantiation of member function 'std::__get_nested_helper<E>::_S_get' requested here
    { return __get_nested_helper<_Ex>::_S_get(__ex); }
                                      ^
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.1/include/g++-v4/bits/nested_exception.h:138:11: note: in instantiation of function template specialization 'std::__get_nested_exception<E>' requested here
      if (__get_nested_exception(__ex))
          ^
test.cpp:6:8: note: in instantiation of function template specialization 'std::throw_with_nested<E>' requested here
  std::throw_with_nested(E(42));
      ^

std::throw_with_nested在c++ 11期望一个参数与多态类型或这是一个错误在编译器或libstdc++?

这是一个bug。

当我在2009年为libstdc++实现它时,N2619的规范要求E是多态类型,但2011年标准中的最终规范不同,libstdc++中的实现从未改变。

这可能是一个bug。

标准规定std::throw_with_nested:

[[noreturn]] template <class T> void throw_with_nested(T&& t);

Uremove_reference<T>::type.

要求: U应为CopyConstructible

抛出:如果U不是从nested_exception派生的非联合类类型,则抛出一个未指定类型的异常,该异常从Unested_exception公开派生,并从std::forward<T>(t)构造,否则为std::forward<T>(t)

§18.8.6 [except.nested]

它确实看起来像一个bug(参见其他答案),参考§18.8.6/7。如果尚未从std::nested_exception派生,则使用从Enested_exception派生的未指定类型。

作为建议的绕过的工作,当它被修复时,显式地从std::nested_exception 派生或将析构函数实现为虚的;

#include <exception>
struct E : std::nested_exception { E(int) {} };
// Alternative workaround... virtual destructor
// struct E { E(int) {} virtual ~E() {} };
int main() {
 try {
  std::throw_with_nested(E(42));
  return 0;
 }
 catch (E&) {
 }
}
样本。