Hello

I am unsure of the correct way to make this function below(multiply) stop if a condition is true?

The reason why is because of the function type, its not an int, string, void etc, I am unsure how to stop a function whos type is the class name?

Do I use...
return;
return -1;
return EXIT_SUCCESS;
return FAIL;

#include <iostream>

using namespace std;

class set {
      
      public:
             set multiply(const set &other) const;
             
      private:
              int num;
};

set set::multiply(const set &other) const
{
    
    if (num == 0) {
        cout << "Function 'multiply' stopped \n";
        return -1; // is this the correct way to stop/end this function or should I use return; or return EXIT_SUCCESS;
    }
    
}

Dani AI

Generated

Short answer: a function declared to return a set must return a set (or something convertible to it). You cannot use a bare return; in a non-void function, and return -1; only ever works if set happens to have a converting constructor from int (which is fragile and confusing). and touched on the right design questions — whether an invalid parameter is an exceptional condition or a normal "no result" case — and that choice determines the right pattern.

If the absence of a result is a normal possibility, prefer an explicit "no result" return type rather than inventing magic integers. For C++17+ use std::optional so callers must check the result:

std::optional<set> unions(int x) const {
    if (x > setRange) return std::nullopt;
    // build and return a set
}

(see std::optional).

If an out-of-range argument really is a programmer error, throw an exception — document it and use a standard exception type such as std::out_of_range:

if (x > setRange) throw std::out_of_range("x out of range");

(see std::out_of_range). Use exceptions with care (avoid throwing from destructors; document which functions may throw).

Other patterns: return a smart pointer and use nullptr for failure, or provide a bool try_unions(int x, set &out) style function. For library code consider std::expected (C++23) when you want both a value and a rich error reason.

A couple of practical notes: perform the range check early to avoid wasted work; avoid naming your class set (it conflicts with std::set and can confuse readers); and avoid relying on implicit conversions (like returning -1) because they hide bugs and make the API unclear. For the OP (), choose std::optional if a missing result is normal, or throw std::out_of_range if the call is invalid and should be handled as an error.

Recommended Answers

All 4 Replies

Your return value is the type of function that you declared.

For example if you make int sum(int x, int y) { return x+y; }
this function returns an integer.

Your return value is a set and that is a class type you defined.

It looks like you are just returning a value to say it did it. You could get away with declaring the function void and have no return value.

example

void multiply(const set &other)

but if you want it to return the value of the 2 sets multiplying then you want to return int for your num.

example

int multiply(const set &other)
{
return num*set.getNum();
}

I put the attribute getNum() in because num is declared private.

Well it is definately wrong.

The reason is that the method say it will return an object of set, but -1, EXIT_SUCCESS etc is an integer so it will not compile.

The return from a function is based on what will happen later and how bad it is.

For example consider say [icode]set divide(const set& other)[/icode]
in the above. [multiply is a bad choise since 0 * a number is ok.
What options do we have, well we could have

this->num=5 other.num=2 

that would be a slight problem, since 5/2 in the set of integers is 2. Maybe you need a warning? Or we could hvae other.num=0 and things have gone very wrong.

There are four main options:

(a) set an other variable : status and put the status of the result but always return a valid output.
(b) set the output (if it is a class) to some-predefined error status.
(c) throw an exception
(d) exit the code.

First off, (d) well if the whole thing has gone wrong nobody will want to be running the code, but it can be a bit drastic.
(c) This is a bit drastic still, because if there is no catch block then it is the same as (d), however it allows large objects to be propergated back, and clears up the memory properly in most cases [don't use in a constructor unless VERY careful, never use in a destructor.]
(b) Often acceptable, but beware that it is likely this should be tested for, that is often why exceptions are preferred since they force testing.
(a) Same as (b) but disjoint and that can cause some problems.

There are no hard rules, many many function return only their error status, and the other changes happen to function variables.
The STL uses both exceptions and valid but requiring checking objects, e.g. find returns the end() iterator when nothing is found.

It is a question of program architecture and likely user. E.g just you, some one using your library, etc.

Well it is definately wrong.

The reason is that the method say it will return an object of set, but -1, EXIT_SUCCESS etc is an integer so it will not compile.

The return from a function is based on what will happen later and how bad it is.

For example consider say [icode]set divide(const set& other)[/icode]
in the above. [multiply is a bad choise since 0 * a number is ok.
What options do we have, well we could have
this->num=5 other.num=2 that would be a slight problem, since 5/2 in the set of integers is 2. Maybe you need a warning? Or we could hvae other.num=0 and things have gone very wrong.

There are four main options:

(a) set an other variable : status and put the status of the result but always return a valid output.
(b) set the output (if it is a class) to some-predefined error status.
(c) throw an exception
(d) exit the code.

Like you said, I am trying to stop the function if I encounter an error

But I am unsure how to stop the function becuase of its type, if it was an int function I'd just use return -1;

The above code was a simple example; this is what I am really doing:

set set::unions(int x) const
{
    // pre : none
    // post : returns the union of this set and x (if x in range)

    int setRange = getUpperRange();

    // Check that x is within setlist vectors' range
    if (x > setRange) {
        cout << "Cannot perform action: parameter is outside setlist vector range \n";
        return -1;
    }

/// there alot of other stuff that will be performed, that goes here, if the above condition is not true
}

I have the error message like you suggested but I dont know how to stop the function if I run into an error?

It depends : you have two options:

(a) leave the set unchanged. Simple do return *this; .
You will have to have an suitable copy constructor in you class but it is likely that you have one set(const set&) (b) ok, big error, then throw RangeError; or some such exception. [Note you have two write a RangeError class or use a STL exception class] But be careful to ensure you catch it latter.

However, you cant return -1. That is not acceptable (unless you can cast -1 to a set??? -- you might have added a suitable operator -- doesn't seem like a good idea but .... )

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.