C++11, BS book extract, part II, chapter 12 + 13
May 5, 2015 Leave a comment
Parts of a Function Declaration
- [[noreturn]], indicating that the function will not return using the normal call/return mechanism
- override, indicating that it must be overriding a virtual function from a base class
- final, indicating that it cannot be overriden in a derived class
That is, a prefix auto indicates that the return type is placed after the argument list. The suffix return type is preceded by −>.
The essential use for a suffix return type comes in function template declarations in which the return type depends on the arguments. For example:
template<class T, class U> auto product(const vector<T>& x, const vector<U>& y) −> decltype(x∗y);
However, the suffix return syntax can be used for any function.
A constexpr function cannot have side effects, so writing to nonlocal objects is not possible.
If there is a possible ambiguity, an initializer_list parameter takes priority.
Unspecified Number of Arguments
- a variadic template
- an initializer_list as the argument type
- Terminate the argument list with the ellipsis ( … )
Automatic Overload Resolution
- Exact match
- Match using promotions
- Match using standard conversions
- Match using user-defined conversions
- Match using the ellipsis … in a function declaration
Overloading takes place among the members of an overload set. By default, that means the functions of a single scope; functions declared in different non-namespace scopes do not overload.
The C++ standard library provides provides one of the following guarantees for every library operation:
- The basic guarantee for all operations: The basic invariants of all objects are maintained, and no resources, such as memory, are leaked.
- The strong guarantee for key operations: in addition to providing the basic guarantee, either the operation succeeds, or it has no effect.
- The nothrow guarantee for some operations: in addition to providing the basic guarantee, some operations are guaranteed not to throw an exception.
Both the basic guarantee and the strong guarantee are provided on the condition that
- user-supplied operations (such as assignments and swap() functions) do not leave container elements in invalid states
- user-supplied operations do not leak resources
- destructors do not throw exceptions
double compute(double) noexcept; // may not throw an exception. It terminates unconditionally by invoking std::terminate() if exception is thrown.
The noexcept Operator – template<typename T> void my_fct(T& x) noexcept(Is_pod<T>());
The handler is invoked:
- [1] If H is the same type as E
- [2] If H is an unambiguous public base of E
- [3] If H and E are pointer types and [1] or [2] holds for the types to which they refer
- [4] If H is a reference and [1] or [2] holds for the type to which H refers
The guiding principles are:
- Don’t throw an exception while handling an exception.
- Don’t throw an exception that can’t be caught.
The specific rules for calling terminate() are
• When no suitable handler was found for a thrown exception
• When a noexcept function tries to exit with a throw
• When a destructor invoked during stack unwinding tries to exit with a throw
• When code invoked to propagate an exception (e.g., a copy constructor) tries to exit with a throw
• When someone tries to rethrow ( throw; ) when there is no current exception being handled
• When a destructor for a statically allocated or thread-local object tries to exit with a throw
• When an initializer for a statically allocated or thread-local object tries to exit with a throw
• When a function invoked as an atexit() function tries to exit with a throw
By default, terminate() will call abort(). If that is not acceptable, the user can provide a terminate handler function by a call std::set_terminate() from <exception>
If an exception is not caught on a thread, std::terminate() is called.