考虑以下(我认为非法)代码:
#include <exception>
#include <string>
using namespace std;
int main()
{
try {
try {
throw string ("x");
}
catch(string& x)
{
throw_with_nested(string("xx"));
}
}
catch(...)
{
auto ep = current_exception();
}
return 0;
}
使用clang ++针对libc ++编译此代码编译。
使用g ++反对libstdc ++:
In file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/exception:153:0,
from main.cpp:1:
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/nested_exception.h: In instantiation of �static const std::nested_exception* std::__get_nested_helper<_Ex>::_S_get(const _Ex&) [with _Ex = std::basic_string<char>]�:
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/nested_exception.h:104:51: required from �const std::nested_exception* std::__get_nested_exception(const _Ex&) [with _Ex = std::basic_string<char>]�
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/nested_exception.h:138:38: required from �void std::throw_with_nested(_Ex) [with _Ex = std::basic_string<char>]�
main.cpp:15:43: required from here
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/nested_exception.h:90:59: error: cannot dynamic_cast �& __ex� (of type �const class std::basic_string<char>*�) to type �const class std::nested_exception*� (source type is not polymorphic)
{ return dynamic_cast<const nested_exception*>(&__ex); }
^
据我了解,std::throw_with_nested<T>
要求T是多态的,而std :: string不是多态的。所以libstdc ++在这里正在做正确的事(tm)。
这里有什么可以提供的吗?
答案 0 :(得分:3)
N3337 [except.nested] / 5,6
[[noreturn]] template <class T> void throw_with_nested(T&& t);
让
U
成为remove_reference<T>::type
。
5.要求:U
CopyConstructible
。
6.抛出:如果U
不是非联合类类型 派生自nested_exception
,是从U
和nested_exception
公开派生并由std::forward<T>(t)
构建的未指定类型的例外,否则为std::forward<T>(t)
。
还要考虑nested_exception
是多态的,因为它有一个虚拟析构函数([except.nested] / 2):
[注意:
nested_exception
有一个虚拟析构函数来实现它 多态类。可以使用dynamic_cast
测试其存在。 - 结束说明]
实际抛出的异常类型总是多态的。但U
并非如此 - 只需CopyConstructible
,如需要部分所述。
因此libstdc ++的实现无效。它应该在内部专门针对is_base_of<nested_exception, U>::value
为false
的类型。