In C++, you can specify that a function may or may not throw an exception by using an exception specifier. For example:
在c++中,您可以指定一个函数可以使用异常说明符,也可能不会抛出异常。例如:
void foo() throw(); // guaranteed not to throw an exception
void bar() throw(int); // may throw an exception of type int
void baz() throw(...); // may throw an exception of some unspecified type
I'm doubtful about actually using them because of the following:
我怀疑是否真的使用它们是因为
- The compiler doesn't really enforce exception specifiers in any rigorous way, so the benefits are not great. Ideally, you would like to get a compile error.
- 编译器不会以任何严格的方式强制异常说明符,所以好处不是很大。理想情况下,您希望得到一个编译错误。
- If a function violates an exception specifier, I think the standard behaviour is to terminate the program.
- 如果函数违反了异常说明符,我认为标准的行为是终止程序。
- In VS.Net, it treats throw(X) as throw(...), so adherence to the standard is not strong.
- 在VS.Net中,它将throw(X)视为throw(…),因此遵循标准的程度并不强。
Do you think exception specifiers should be used?
Please answer with "yes" or "no" and provide some reasons to justify your answer.
您认为应该使用异常说明符吗?请用“是”或“否”来回答,并提供一些理由来证明你的答案。
14 个解决方案
#1
86
No.
不。
Here are several examples why:
以下是几个例子:
-
Template code is impossible to write with exception specifications,
模板代码不可能编写异常规范,
template<class T> void f( T k ) { T x( k ); x.x(); }
The copies might throw, the parameter passing might throw, and
x()
might throw some unknown exception.拷贝可能抛出,参数传递可能抛出,x()可能抛出一些未知的异常。
-
Exception-specifications tend to prohibit extensibility.
异常规范倾向于禁止可扩展性。
virtual void open() throw( FileNotFound );
might evolve into
可能演变成
virtual void open() throw( FileNotFound, SocketNotReady, InterprocessObjectNotImplemented, HardwareUnresponsive );
You could really write that as
你可以把它写成
throw( ... )
The first is not extensible, the second is overambitious and the third is really what you mean, when you write virtual functions.
第一个是不可扩展的,第二个是过于雄心勃勃,第三个是您在编写虚函数时的真正含义。
-
Legacy code
遗留代码
When you write code which relies on another library, you don't really know what it might do when something goes horribly wrong.
当您编写依赖于另一个库的代码时,您实际上并不知道当某些事情发生严重错误时它会做什么。
int lib_f(); void g() throw( k_too_small_exception ) { int k = lib_f(); if( k < 0 ) throw k_too_small_exception(); }
g
will terminate, whenlib_f()
throws. This is (in most cases) not what you really want.std::terminate()
should never be called. It is always better to let the application crash with an unhandled exception, from which you can retrieve a stack-trace, than to silently/violently die.当lib_f()抛出时,g将终止。这(在大多数情况下)不是你真正想要的。终止()不应该被调用。让应用程序以未处理的异常崩溃(您可以从该异常中检索堆栈跟踪)总是比以静默/暴力方式死要好。
-
Write code that returns common errors and throws on exceptional occasions.
编写在特殊情况下返回常见错误和抛出的代码。
Error e = open( "bla.txt" ); if( e == FileNotFound ) MessageUser( "File bla.txt not found" ); if( e == AccessDenied ) MessageUser( "Failed to open bla.txt, because we don't have read rights ..." ); if( e != Success ) MessageUser( "Failed due to some other error, error code = " + itoa( e ) ); try { std::vector<TObj> k( 1000 ); // ... } catch( const bad_alloc& b ) { MessageUser( "out of memory, exiting process" ); throw; }
Nevertheless, when your library just throws your own exceptions, you can use exception specifications to state your intent.
然而,当您的库仅仅抛出您自己的异常时,您可以使用异常规范来声明您的意图。
#2
42
Avoid exception specifications in C++. The reasons you give in your question are a pretty good start for why.
避免使用c++中的异常规范。你在问题中给出的原因是一个很好的开始。
See Herb Sutter's "A Pragmatic Look at Exception Specifications".
参见赫伯·萨特的“异常规范的实用主义观点”。
#3
14
I think the standardly except convention (for C++)
Exception specifiers were an experiment in the C++ standard that mostly failed.
The exception being that the no throw specifier is useful but you should also add the appropriate try catch block internally to make sure the code matches the specifier. Herb Sutter has a page on the subject. Gotch 82
我认为除了约定(对于c++)异常说明符之外的标准异常是c++标准中的一个实验,它几乎失败了。例外的是,no throw说明符很有用,但是您还应该在内部添加适当的try catch块,以确保代码与说明符匹配。赫伯·萨特在这一主题上有一页。Gotch 82
In a addition I think it is worth describing Exception Guarantees.
另外,我认为它值得描述异常保证。
These are basically documentation on how the state of an object is affected by exceptions escaping a method on that object. Unfortunately they are not enforced or otherwise mentioned by the compiler.
Boost and Exceptions
这些基本上都是关于一个对象的状态如何受到在该对象上转义的异常的影响的文档。不幸的是,编译器并没有强制或提到它们。增加和异常
Exception Guarantees
No Guarantee:
There is no guarantee about the state of the object after an exception escapes a method
In these situations the object should no longer be used.在这种情况下,不能保证在异常转义方法之后,对象的状态将不再被使用。
Basic Guarantee:
In nearly all situations this should be the minimum guarantee a method provides.
This guarantees the object's state is well defined and can still be consistently used.在几乎所有的情况下,这应该是方法提供的最低保证。这保证了对象的状态定义良好,并且仍然可以持续使用。
Strong Guarantee: (aka Transactional Guarantee)
This guarantees that the method will complete successfully
Or an Exception will be thrown and the objects state will not change.这保证了方法将成功完成,或者抛出异常,并且对象状态不会改变。
No Throw Guarantee:
The method guarantees that no exceptions are allowed to propagate out of the method.
All destructors should make this guarantee.
| N.B. If an exception escapes a destructor while an exception is already propagating
| the application will terminate该方法保证不允许任何异常从该方法传播出去。所有的析构函数都应该做这个保证。如果异常在传播|时转义析构函数,则应用程序将终止
#4
8
gcc will emit warnings when you violate exception specifications. What I do is to use macros to use the exception specifications only in a "lint" mode compile expressly for checking to make sure the exceptions agree with my documentation.
当您违反异常规范时,gcc将发出警告。我所做的是使用宏只在“lint”模式下使用异常规范,以明确编译以确保异常与我的文档一致。
#5
7
The only useful exception specifier is "throw()", as in "doesn't throw".
唯一有用的异常说明符是“throw()”,如“不扔”。
#6
4
No. If you use them and an exception is thrown that you did not specify, either by your code or code called by your code, then the default behavior is to promptly terminate your program.
不。如果您使用它们,并且抛出了一个您没有指定的异常,或者您的代码或代码调用的代码,那么默认行为就是立即终止您的程序。
Also, I believe their use has been deprecated in current drafts of the C++0x standard.
另外,我认为在c++ 0x标准的当前草案中已经不使用它们了。
#7
4
Exception specifications are not wonderfully useful tools in C++. However, there /is/ a good use for them, if combined with std::unexpected.
异常规范在c++中不是非常有用的工具。然而,如果与std:::unexpected相结合,则可以使用/is/ a good use for them。
What I do in some projects is code with exception specifications, and then call set_unexpected() with a function that will throw a special exception of my own design. This exception, upon construction, gets a backtrace (in a platform-specific manner) and is derived from std::bad_exception (to allow it to be propagated if desired). If it causes a terminate() call, as it usually does, the backtrace is printed by what() (as well as the original exception that caused it; not to hard to find that) and so I get information of where my contract was violated, such as what unexpected library exception was thrown.
在某些项目中,我所做的是编写带有异常规范的代码,然后使用一个函数调用set_unexpected(),这个函数将抛出我自己设计的一个特殊异常。构造时,此异常会得到一个回溯(以特定于平台的方式),并派生自std::bad_exception(以便在需要时传播它)。如果它引起一个terminate()调用(通常是这样做的),那么返回跟踪将由what()(以及导致它的原始异常)打印出来;不难发现),因此我得到了关于我的合同被违反的地方的信息,比如抛出了什么意外的库异常。
If I do this, I never allow propagation of library exceptions (except std ones) and derive all my exceptions from std::exception. If a library decides to throw, I will catch and convert into my own hierarchy, allowing for me to always control the code. Templated functions that call dependent functions should avoid exception specifications for obvious reasons; but it's rare to have a templated function interface with library code anyway (and few libraries really use templates in a useful manner).
如果我这样做,我就不允许传播库异常(除了std异常),并从std::exception派生所有异常。如果库决定抛出,我将捕获并转换为我自己的层次结构,允许我始终控制代码。调用相关函数的模板化函数应该出于明显的原因避免异常规范;但是很少有模板化的函数接口和库代码(而且很少有库真正以一种有用的方式使用模板)。
#8
3
If you're writing code that will be used by people that would rather look at the function declaration than any comments around it, then a specification will tell them which exceptions they might want to catch.
如果您正在编写的代码将被那些宁愿查看函数声明而不愿查看它周围的任何注释的人使用,那么规范将告诉他们可能希望捕获哪些异常。
Otherwise I don't find it particularly useful to use anything but throw()
to indicate that it doesn't throw any exceptions.
否则,我发现使用抛出()以外的任何东西表示它不会抛出任何异常不是特别有用。
#9
3
A "throw()" specification allows the compiler to perform some optimisations when doing code flow analysis if it know that function will never throw an exception (or at least promises to never throw an exception). Larry Osterman talks about this briefly here:
“throw()”规范允许编译器在执行代码流分析时执行一些优化,如果它知道函数永远不会抛出异常(或者至少保证不会抛出异常)。拉里·奥斯特曼在这里简单地谈到了这个问题:
http://blogs.msdn.com/larryosterman/archive/2006/03/22/558390.aspx
http://blogs.msdn.com/larryosterman/archive/2006/03/22/558390.aspx
#10
2
Generally I would not use exception specifiers. However, in cases where if any other exception were to come from the function in question that the program would definitively be unable to correct, then it can be useful. In all cases, make sure to document clearly what exceptions could be expected from that function.
一般来说,我不会使用异常说明符。但是,如果有任何其他异常来自该程序肯定无法纠正的函数,那么它可能是有用的。在所有情况下,确保文档清楚地记录了该函数所期望的异常。
Yes, the expected behavior of a non-specified exception being thrown from a function with exception specifiers is to call terminate().
是的,从带有异常说明符的函数中抛出的非指定异常的预期行为是调用terminate()。
I will also note that Scott Meyers addresses this subject in More Effective C++. His Effective C++ and More Effective C++ are highly recommended books.
我还将注意到,Scott Meyers用更有效的c++处理了这个问题。他有效的c++和更有效的c++都是非常推荐的书籍。
#11
2
Yes, if you're into internal documentation. Or maybe writing a libary that others will use, so that they can tell what happens without consulting the documentation. Throwing or not throwing can be considered part of the API, almost like the return value.
是的,如果你喜欢内部文件。或者写一个供其他人使用的libary,这样他们就可以在不查阅文档的情况下知道发生了什么。抛出或不抛出可以看作是API的一部分,就像返回值一样。
I agree, they are not really useful for enforcing correctness Java style in the compiler, but it's better than nothing or haphazard comments.
我同意,它们对于在编译器中执行正确的Java风格并不是很有用,但是它总比什么都没有或随意的评论好。
#12
2
They can be useful for unit testing so that when writing tests you know what to expect the function to throw when it fails, but there is no enforcement surrounding them in the compiler. I think that they are extra code that is not necessary in C++. Which ever you choose all that you should be sure of is that you follow the same coding standard across the project and the team members so that your code remains readable.
它们在单元测试中很有用,这样当编写测试时,您知道当它失败时,应该期望函数抛出什么,但是在编译器中没有强制执行。我认为它们是c++中不必要的额外代码。无论您选择什么,您都应该确保在整个项目和团队成员之间遵循相同的编码标准,以便您的代码保持可读性。
#13
0
From the article:
从这篇文章:
http://www.boost.org/community/exception_safety.html
http://www.boost.org/community/exception_safety.html
“It is well known to be impossible to write an exception-safe generic container.” This claim is often heard with reference to an article by Tom Cargill [4] in which he explores the problem of exception-safety for a generic stack template. In his article, Cargill raises many useful questions, but unfortunately fails to present a solution to his problem.1 He concludes by suggesting that a solution may not be possible. Unfortunately, his article was read by many as “proof” of that speculation. Since it was published there have been many examples of exception-safe generic components, among them the C++ standard library containers.
众所周知,不可能编写异常安全的通用容器。这种说法经常被引用Tom Cargill[4]的一篇文章中,他在文中探讨了一个通用堆栈模板的异常安全性问题。在他的文章中,卡吉尔提出了许多有用的问题,但不幸的是,他没有提出解决问题的办法。他最后提出解决方案可能不可能。不幸的是,他的文章被许多人视为这种猜测的“证据”。自从它发布以来,有许多例外安全的通用组件的例子,其中包括c++标准库容器。
And indeed I can think of ways to make template classes exception safe. Unless you don't have control over all the sub-classes then you may have a problem anyway. To do this one could create typedefs in your classes that define the exceptions thrown by various template classes. This think the problem is as always tacking it on afterwards as opposed to designing it in from the start, and I think it's this overhead that's the real hurdle.
实际上,我可以想出使模板类异常安全的方法。除非你不能控制所有的子类,否则你可能会有问题。要做到这一点,可以在类中创建typedef,它定义由各种模板类抛出的异常。这种想法认为问题总是在之后再加上它,而不是从一开始就设计它,我认为真正的障碍是这种开销。
#14
-1
Exception specifications = rubbish, ask any Java developer over the age of 30
异常规范=垃圾,询问任何30岁以上的Java开发人员
#1
86
No.
不。
Here are several examples why:
以下是几个例子:
-
Template code is impossible to write with exception specifications,
模板代码不可能编写异常规范,
template<class T> void f( T k ) { T x( k ); x.x(); }
The copies might throw, the parameter passing might throw, and
x()
might throw some unknown exception.拷贝可能抛出,参数传递可能抛出,x()可能抛出一些未知的异常。
-
Exception-specifications tend to prohibit extensibility.
异常规范倾向于禁止可扩展性。
virtual void open() throw( FileNotFound );
might evolve into
可能演变成
virtual void open() throw( FileNotFound, SocketNotReady, InterprocessObjectNotImplemented, HardwareUnresponsive );
You could really write that as
你可以把它写成
throw( ... )
The first is not extensible, the second is overambitious and the third is really what you mean, when you write virtual functions.
第一个是不可扩展的,第二个是过于雄心勃勃,第三个是您在编写虚函数时的真正含义。
-
Legacy code
遗留代码
When you write code which relies on another library, you don't really know what it might do when something goes horribly wrong.
当您编写依赖于另一个库的代码时,您实际上并不知道当某些事情发生严重错误时它会做什么。
int lib_f(); void g() throw( k_too_small_exception ) { int k = lib_f(); if( k < 0 ) throw k_too_small_exception(); }
g
will terminate, whenlib_f()
throws. This is (in most cases) not what you really want.std::terminate()
should never be called. It is always better to let the application crash with an unhandled exception, from which you can retrieve a stack-trace, than to silently/violently die.当lib_f()抛出时,g将终止。这(在大多数情况下)不是你真正想要的。终止()不应该被调用。让应用程序以未处理的异常崩溃(您可以从该异常中检索堆栈跟踪)总是比以静默/暴力方式死要好。
-
Write code that returns common errors and throws on exceptional occasions.
编写在特殊情况下返回常见错误和抛出的代码。
Error e = open( "bla.txt" ); if( e == FileNotFound ) MessageUser( "File bla.txt not found" ); if( e == AccessDenied ) MessageUser( "Failed to open bla.txt, because we don't have read rights ..." ); if( e != Success ) MessageUser( "Failed due to some other error, error code = " + itoa( e ) ); try { std::vector<TObj> k( 1000 ); // ... } catch( const bad_alloc& b ) { MessageUser( "out of memory, exiting process" ); throw; }
Nevertheless, when your library just throws your own exceptions, you can use exception specifications to state your intent.
然而,当您的库仅仅抛出您自己的异常时,您可以使用异常规范来声明您的意图。
#2
42
Avoid exception specifications in C++. The reasons you give in your question are a pretty good start for why.
避免使用c++中的异常规范。你在问题中给出的原因是一个很好的开始。
See Herb Sutter's "A Pragmatic Look at Exception Specifications".
参见赫伯·萨特的“异常规范的实用主义观点”。
#3
14
I think the standardly except convention (for C++)
Exception specifiers were an experiment in the C++ standard that mostly failed.
The exception being that the no throw specifier is useful but you should also add the appropriate try catch block internally to make sure the code matches the specifier. Herb Sutter has a page on the subject. Gotch 82
我认为除了约定(对于c++)异常说明符之外的标准异常是c++标准中的一个实验,它几乎失败了。例外的是,no throw说明符很有用,但是您还应该在内部添加适当的try catch块,以确保代码与说明符匹配。赫伯·萨特在这一主题上有一页。Gotch 82
In a addition I think it is worth describing Exception Guarantees.
另外,我认为它值得描述异常保证。
These are basically documentation on how the state of an object is affected by exceptions escaping a method on that object. Unfortunately they are not enforced or otherwise mentioned by the compiler.
Boost and Exceptions
这些基本上都是关于一个对象的状态如何受到在该对象上转义的异常的影响的文档。不幸的是,编译器并没有强制或提到它们。增加和异常
Exception Guarantees
No Guarantee:
There is no guarantee about the state of the object after an exception escapes a method
In these situations the object should no longer be used.在这种情况下,不能保证在异常转义方法之后,对象的状态将不再被使用。
Basic Guarantee:
In nearly all situations this should be the minimum guarantee a method provides.
This guarantees the object's state is well defined and can still be consistently used.在几乎所有的情况下,这应该是方法提供的最低保证。这保证了对象的状态定义良好,并且仍然可以持续使用。
Strong Guarantee: (aka Transactional Guarantee)
This guarantees that the method will complete successfully
Or an Exception will be thrown and the objects state will not change.这保证了方法将成功完成,或者抛出异常,并且对象状态不会改变。
No Throw Guarantee:
The method guarantees that no exceptions are allowed to propagate out of the method.
All destructors should make this guarantee.
| N.B. If an exception escapes a destructor while an exception is already propagating
| the application will terminate该方法保证不允许任何异常从该方法传播出去。所有的析构函数都应该做这个保证。如果异常在传播|时转义析构函数,则应用程序将终止
#4
8
gcc will emit warnings when you violate exception specifications. What I do is to use macros to use the exception specifications only in a "lint" mode compile expressly for checking to make sure the exceptions agree with my documentation.
当您违反异常规范时,gcc将发出警告。我所做的是使用宏只在“lint”模式下使用异常规范,以明确编译以确保异常与我的文档一致。
#5
7
The only useful exception specifier is "throw()", as in "doesn't throw".
唯一有用的异常说明符是“throw()”,如“不扔”。
#6
4
No. If you use them and an exception is thrown that you did not specify, either by your code or code called by your code, then the default behavior is to promptly terminate your program.
不。如果您使用它们,并且抛出了一个您没有指定的异常,或者您的代码或代码调用的代码,那么默认行为就是立即终止您的程序。
Also, I believe their use has been deprecated in current drafts of the C++0x standard.
另外,我认为在c++ 0x标准的当前草案中已经不使用它们了。
#7
4
Exception specifications are not wonderfully useful tools in C++. However, there /is/ a good use for them, if combined with std::unexpected.
异常规范在c++中不是非常有用的工具。然而,如果与std:::unexpected相结合,则可以使用/is/ a good use for them。
What I do in some projects is code with exception specifications, and then call set_unexpected() with a function that will throw a special exception of my own design. This exception, upon construction, gets a backtrace (in a platform-specific manner) and is derived from std::bad_exception (to allow it to be propagated if desired). If it causes a terminate() call, as it usually does, the backtrace is printed by what() (as well as the original exception that caused it; not to hard to find that) and so I get information of where my contract was violated, such as what unexpected library exception was thrown.
在某些项目中,我所做的是编写带有异常规范的代码,然后使用一个函数调用set_unexpected(),这个函数将抛出我自己设计的一个特殊异常。构造时,此异常会得到一个回溯(以特定于平台的方式),并派生自std::bad_exception(以便在需要时传播它)。如果它引起一个terminate()调用(通常是这样做的),那么返回跟踪将由what()(以及导致它的原始异常)打印出来;不难发现),因此我得到了关于我的合同被违反的地方的信息,比如抛出了什么意外的库异常。
If I do this, I never allow propagation of library exceptions (except std ones) and derive all my exceptions from std::exception. If a library decides to throw, I will catch and convert into my own hierarchy, allowing for me to always control the code. Templated functions that call dependent functions should avoid exception specifications for obvious reasons; but it's rare to have a templated function interface with library code anyway (and few libraries really use templates in a useful manner).
如果我这样做,我就不允许传播库异常(除了std异常),并从std::exception派生所有异常。如果库决定抛出,我将捕获并转换为我自己的层次结构,允许我始终控制代码。调用相关函数的模板化函数应该出于明显的原因避免异常规范;但是很少有模板化的函数接口和库代码(而且很少有库真正以一种有用的方式使用模板)。
#8
3
If you're writing code that will be used by people that would rather look at the function declaration than any comments around it, then a specification will tell them which exceptions they might want to catch.
如果您正在编写的代码将被那些宁愿查看函数声明而不愿查看它周围的任何注释的人使用,那么规范将告诉他们可能希望捕获哪些异常。
Otherwise I don't find it particularly useful to use anything but throw()
to indicate that it doesn't throw any exceptions.
否则,我发现使用抛出()以外的任何东西表示它不会抛出任何异常不是特别有用。
#9
3
A "throw()" specification allows the compiler to perform some optimisations when doing code flow analysis if it know that function will never throw an exception (or at least promises to never throw an exception). Larry Osterman talks about this briefly here:
“throw()”规范允许编译器在执行代码流分析时执行一些优化,如果它知道函数永远不会抛出异常(或者至少保证不会抛出异常)。拉里·奥斯特曼在这里简单地谈到了这个问题:
http://blogs.msdn.com/larryosterman/archive/2006/03/22/558390.aspx
http://blogs.msdn.com/larryosterman/archive/2006/03/22/558390.aspx
#10
2
Generally I would not use exception specifiers. However, in cases where if any other exception were to come from the function in question that the program would definitively be unable to correct, then it can be useful. In all cases, make sure to document clearly what exceptions could be expected from that function.
一般来说,我不会使用异常说明符。但是,如果有任何其他异常来自该程序肯定无法纠正的函数,那么它可能是有用的。在所有情况下,确保文档清楚地记录了该函数所期望的异常。
Yes, the expected behavior of a non-specified exception being thrown from a function with exception specifiers is to call terminate().
是的,从带有异常说明符的函数中抛出的非指定异常的预期行为是调用terminate()。
I will also note that Scott Meyers addresses this subject in More Effective C++. His Effective C++ and More Effective C++ are highly recommended books.
我还将注意到,Scott Meyers用更有效的c++处理了这个问题。他有效的c++和更有效的c++都是非常推荐的书籍。
#11
2
Yes, if you're into internal documentation. Or maybe writing a libary that others will use, so that they can tell what happens without consulting the documentation. Throwing or not throwing can be considered part of the API, almost like the return value.
是的,如果你喜欢内部文件。或者写一个供其他人使用的libary,这样他们就可以在不查阅文档的情况下知道发生了什么。抛出或不抛出可以看作是API的一部分,就像返回值一样。
I agree, they are not really useful for enforcing correctness Java style in the compiler, but it's better than nothing or haphazard comments.
我同意,它们对于在编译器中执行正确的Java风格并不是很有用,但是它总比什么都没有或随意的评论好。
#12
2
They can be useful for unit testing so that when writing tests you know what to expect the function to throw when it fails, but there is no enforcement surrounding them in the compiler. I think that they are extra code that is not necessary in C++. Which ever you choose all that you should be sure of is that you follow the same coding standard across the project and the team members so that your code remains readable.
它们在单元测试中很有用,这样当编写测试时,您知道当它失败时,应该期望函数抛出什么,但是在编译器中没有强制执行。我认为它们是c++中不必要的额外代码。无论您选择什么,您都应该确保在整个项目和团队成员之间遵循相同的编码标准,以便您的代码保持可读性。
#13
0
From the article:
从这篇文章:
http://www.boost.org/community/exception_safety.html
http://www.boost.org/community/exception_safety.html
“It is well known to be impossible to write an exception-safe generic container.” This claim is often heard with reference to an article by Tom Cargill [4] in which he explores the problem of exception-safety for a generic stack template. In his article, Cargill raises many useful questions, but unfortunately fails to present a solution to his problem.1 He concludes by suggesting that a solution may not be possible. Unfortunately, his article was read by many as “proof” of that speculation. Since it was published there have been many examples of exception-safe generic components, among them the C++ standard library containers.
众所周知,不可能编写异常安全的通用容器。这种说法经常被引用Tom Cargill[4]的一篇文章中,他在文中探讨了一个通用堆栈模板的异常安全性问题。在他的文章中,卡吉尔提出了许多有用的问题,但不幸的是,他没有提出解决问题的办法。他最后提出解决方案可能不可能。不幸的是,他的文章被许多人视为这种猜测的“证据”。自从它发布以来,有许多例外安全的通用组件的例子,其中包括c++标准库容器。
And indeed I can think of ways to make template classes exception safe. Unless you don't have control over all the sub-classes then you may have a problem anyway. To do this one could create typedefs in your classes that define the exceptions thrown by various template classes. This think the problem is as always tacking it on afterwards as opposed to designing it in from the start, and I think it's this overhead that's the real hurdle.
实际上,我可以想出使模板类异常安全的方法。除非你不能控制所有的子类,否则你可能会有问题。要做到这一点,可以在类中创建typedef,它定义由各种模板类抛出的异常。这种想法认为问题总是在之后再加上它,而不是从一开始就设计它,我认为真正的障碍是这种开销。
#14
-1
Exception specifications = rubbish, ask any Java developer over the age of 30
异常规范=垃圾,询问任何30岁以上的Java开发人员