Hello, OnlineGDB Q&A section lets you put your programming query to fellow community users. Asking a solution for whole assignment is strictly not allowed. You may ask for help where you are stuck. Try to add as much information as possible so that fellow users can know about your problem statement easily.

How to throw exceptions for the [] operator in C++?

+7 votes
asked Dec 14, 2021 by Areeb Sherjil (1,960 points)
I overloaded the [] subscript operator to extract the shared_ptr inside a linked list. If the index argument of the [] is incorrect then I made a shared_ptr null pointer that is being returned. How can I change this to use exceptions?

using SharedBox = std::shared_ptr<Box>;

static inline SharedBox nullBox{}; // this is nullbox

code snippet, I commented out the exception

SharedBox& Truckload::operator[](size_t index) const
{
    size_t count{};             // Package count
    for (Package* package{ m_head }; package; package = package->m_next)
    {
        if (count++ == index)      // Up to index yet?
            return package->m_box;   // If so return the pointer to Box
    }

 /*   try
    {
        throw std::out_of_range("Array index incorrect.\n");
    }
    catch (const std::out_of_range& out1)
    {
        std::cerr << out1.what();
        // what to do here to keep the program running ?
    }
    */
    return nullBox; // I want to get rid of this
}

(I am using linked list for educational purposes, I know that the std library has one.)

1 Answer

0 votes
answered Dec 14, 2021 by Peter Minarik (86,900 points)
selected Dec 15, 2021 by Areeb Sherjil
 
Best answer

I'm not sure what's the dilemma here.

Why can't you just simply throw an exception when the give index was not found?

SharedBox& Truckload::operator[](size_t index) const
{
    size_t count{};                 // Package count
    for (Package* package{ m_head }; package; package = package->m_next)
    {
        if (count++ == index)      // Up to index yet?
            return package->m_box; // If so return the pointer to Box
    }

    throw std::out_of_range("Array index incorrect.");
}

Something else: what's the purpose of inlining the nullBox?

commented Dec 15, 2021 by Areeb Sherjil (1,960 points)
so no need to use try and catch block for throwing exceptions from the std library ?(Inline is used in modern C++ programming to reduce overheads)
commented Dec 15, 2021 by Areeb Sherjil (1,960 points)
Also the code does not work when using only throw like you showed above. It gives error: "Unhandled exception"
commented Dec 15, 2021 by Peter Minarik (86,900 points)
Of course, your program will say "Unhandled Exception", if you do not handle it.

Since your [] can throw an exception, the caller should handle it.

E.g.:

try
{
    auto bar = load[5]; // This calls your operator overloading.
    bar.Foo();
}
catch (const std::out_of_range & exception)
{
    // Handle exception
}
commented Dec 15, 2021 by Areeb Sherjil (1,960 points)
Thanks this works now. To answer your question about 'inline' variables. This is does not have to be used. The reason for this is simply because inline static variables can be initialised INSIDE a class whereas regular static variables can be declared inside a class but have to be initialised OUTSIDE the class. A C++ software engineer explains:
"
  Caution: in the text, we suggest to add

    static SharedBox nullBox{};

  to the Truckload class definition. This will not compile.
  In-class definitions of non-const static members are only allowed
  if you add the inline keyword, as we did in this solution.
  See Chapter 12 for more explanation,
  and for the alternative of defining the member out-of-class.
"
commented Dec 15, 2021 by Peter Minarik (86,900 points)
I have never used inline for such a purpose. I have been always happy setting the value in a source file:



-- MyClass.h --
#pragma once

#include <memory>

class MyClass
{
private:
    static const int _value = 3; // You can set a const value to a literal
    
    static const std::shared_ptr<MyClass> NullClass; // If the value is not a literal, it can be set in a source file

public:
    MyClass();
};



-- MyClass.cpp --
#include "MyClass.h"

#include <iostream>

const std::shared_ptr<MyClass> MyClass::NullClass = std::shared_ptr<MyClass>();

MyClass::MyClass()
{
    std::cout << "MyClass: " << _value << std::endl;
}
commented Dec 15, 2021 by Areeb Sherjil (1,960 points)
thanks for this
Welcome to OnlineGDB Q&A, where you can ask questions related to programming and OnlineGDB IDE and and receive answers from other members of the community.
...