Open In App

noexcept Operator in C++ 11

Last Updated : 22 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Exception handling is an important concept in C++. Keywords like ‘try’, ‘catch’, and ‘throw’ are often associated with exception handling. Although these keywords are very powerful on their own we need another more efficient method to operate on them. Hence, noexcept operator was introduced in C++ 11.

noexcept Operator in C++

In C++, the noexcept operator is a compile-time operator that is used to check whether an expression will throw an exception. It checks the exception specification of the functions, but functions are not called or evaluated at runtime. The compiler checks the results based on the function declaration.

Also, when creating a function template, we can use noexcept it to specify whether the function might throw exceptions or not for some specific data types.

Note: The noexcept operator does not actually evaluate the expression passed in the parameters. It simply checks whether the given expression will throw an exception or not.

Syntax of noexcept Operator

noexcept(expression)

Parameters

expression: It is the expression we want to evaluate.

Return Value

The function does not return any value. The result is true if the expression is guaranteed to not throw exceptions, otherwise, the result is false.

Example of noexcept Operator

Example 1:

C++




// Java Program to demonstrate
// use of use of the noexcept specifier
#include <iostream>
using namespace std;
  
// Function that may throw an exception
int divide(int a, int b)
{
    if (b == 0) {
        throw runtime_error("Error: Division by zero");
    }
    return a / b;
}
  
// Function that will not throw any exceptions (using
// noexcept)
double safeDivide(double a, double b) noexcept
{
    if (b == 0) {
        // In this case, std::terminate will be called if b
        // is zero
        cerr << "Error: Division by zero in safeDivide"
             << std::endl;
        terminate();
    }
    return a / b;
}
  
int main()
{
    cout << "noexcept value for divide(): "
         << noexcept(divide(10, 0)) << "\n";
  
    cout << "noexcept value for safeDivide(): "
         << noexcept(safeDivide(10.0, 0.0));
  
    return 0;
}


Output

noexcept value for divide(): 0
noexcept value for safeDivide(): 1




Explanation of the above method:

In the above example, the function safeDivide() with noexcept specifier makes the compiler assume that it’s a non-exception throwing function. The noexcept operator gets this and returns true, whereas for divide() there is no such specifier hence it value of noexcept operator is false.

If we remove the noexcept keyword from the safeDivide() then the value of the noexcept operator for the safeDivide() will be false. If a function with noexcept specifier has a potential exception during runtime then the compiler will show undefined behavior. Thus it is the job of the programmer to check function with zero exceptions is declared with noexcept specifier.

Example 2: C++ code to demonstrate the use of the noexcept specifier with a function template

C++




// C++ code to demonstrate the use of the
// noexcept specifier with a function template
#include <bits/stdc++.h>
using namespace std;
  
template <typename T>
void process(const T& value)
    noexcept(noexcept(declval<T>().size()))
{
    // Try to call the size() member function of T
    // If T's size() can throw, this function won't be
    // noexcept for T
    // If T's size() is noexcept, this
    // function will be noexcept for T
    cout << "Size: " << value.size() << endl;
}
  
// main function
int main()
{
    vector<int> numbers = { 1, 2, 3, 4, 5 };
  
    // Won't throw exceptions for std::vector
    process(numbers);
    // May throw exceptions for int
    process(42);
  
    return 0;
}


Output

./Solution.cpp: In instantiation of 'void process(const T&) [with T = int]':
./Solution.cpp:23:15:   required from here
./Solution.cpp:5:6: error: request for member 'size' in 'std::declval<int>()', which is of non-class type 'int'
 void process(const T& value)
      ^
./Solution.cpp: In instantiation of 'void process(const T&) [with T = int]':
./Solution.cpp:23:15:   required from here
./Solution.cpp:5:6: error: request for member 'size' in 'std::declval<int>()', which is of non-class type 'int...


Explanation of the above method:

Fundamental types like int do not have a size() member function. The size() member function is specific to container types like std::vector, std::string, etc., where it returns the number of elements in the container. That is why it throws an exception.

When to use the noexcept operator?

  • You have the guarantee that the function will not throw any exception in any case.
  • You want to optimize the performance by allowing the compiler to skip the process of exception handling which leads to faster execution of the program.

When not to use the noexcept operator?

  • Your function can throw exceptions, or if you’re not sure about its exception safety.
  • When you are dealing with destructors as noexcept destructor can lead to undefined behavior, when exceptions are thrown during object destruction.


Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads