为什么这不能编译(尝试使用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));
^
C ++ 11中的std::throw_with_nested
是否期望具有多态类型的参数或者这是编译器或libstdc ++中的错误?
答案 0 :(得分:16)
这是一个错误。
2009年libstdc ++的I implemented it时N2619中的规范要求E
是多态类型,但2011标准中的最终规范是不同的,并且libstdc ++中的实现从未改变。
答案 1 :(得分:8)
这似乎是一个错误。
标准说明std::throw_with_nested
:
[[noreturn]] template <class T> void throw_with_nested(T&& t);
让
U
为remove_reference<T>::type.
要求:
U
应为CopyConstructible
。抛出:如果
U
是不是从nested_exception
派生的非联合类类型,则是从U
公开派生的未指定类型的例外和nested_exception
并由std::forward<T>(t)
构建,否则为std::forward<T>(t)
。§18.8.6[except.nested]
答案 2 :(得分:3)
确实看起来像一个bug(参见其他答案),参考§18.8.6/ 7。如果尚未从std::nested_exception
派生,则使用源自E
和nested_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&) {
}
}
示例here。