Validate noexcept guarantees

Only mark functions as `noexcept` when you can guarantee they won't throw exceptions under any circumstances. Common pitfalls include: 1. **Hidden allocations**: Operations like vector operations, `std::make_tuple`, or working with collections might allocate memory and throw.

copy reviewer prompt

Prompt

Reviewer Prompt

Only mark functions as noexcept when you can guarantee they won’t throw exceptions under any circumstances. Common pitfalls include:

  1. Hidden allocations: Operations like vector operations, std::make_tuple, or working with collections might allocate memory and throw.
  2. Dependent types: When using templates, the operations performed on template parameters might throw.
  3. Non-noexcept components: If a class member or base class has non-noexcept operations, derived classes shouldn’t blindly use noexcept.

For complex templated code, consider compile-time validation:

// Before marking a templated function as noexcept
template <typename DataDrivenPaintProperty, typename Evaluated>
static bool isConstant(const Evaluated& evaluated) noexcept {
    // How do you know all operations here are truly noexcept?
    return evaluated.template get<DataDrivenPaintProperty>().isConstant();
}

// Better: Add compile-time verification
template <typename DataDrivenPaintProperty, typename Evaluated>
static bool isConstant(const Evaluated& evaluated) noexcept {
    using ReturnType = decltype(evaluated.template get<DataDrivenPaintProperty>());
    static_assert(std::is_nothrow_invocable_v<decltype(&ReturnType::isConstant), ReturnType&>,
                  "isConstant() must be noexcept");
    return evaluated.template get<DataDrivenPaintProperty>().isConstant();
}

When in doubt, err on the side of caution and omit noexcept. Incorrect noexcept specifications can lead to program termination if an exception is thrown, which is worse than having a potentially throwing function not marked as noexcept.

Source discussions