C++ Break out of a function at an early stage
C++ Break out of a function at an early stage
I have two questions.
The first is about working with functions. I need to break out of a function at an early stage under a condition.
For example:
std::string concat(std::string& x, std::string& y, std::vector<std::string>& vec)
{
if (atoi(x.c_str()) < 0)
{
return;
}
else {
std::string concatStr = y + x;
top_back(vec);
top_back(vec);
return concatStr;
}
}
As you can see, the function must return a string, but if the string x(which i of course convert to int) is less than 0, then I theoretically should break out of the function.
The problem with writing just return;
is that the compiler tells me that it needs to return a value.
return;
The second question is how can I remove the last line from the console?
That's connected with the first question, as someone suggested that return "";
is a good workaround, but it writes a blank space into the console, which in my case with the program I'm writing is not good and causes problems.
return "";
std::optional
boost::optional
Nope, i don't have to. How can i implement std::optional?
– Christian Panov
Jun 29 at 21:04
Well now i notice that even my compiler supporting C++17, it still keeps telling me that for the usage of std::optional, i need c++17.
– Christian Panov
Jun 29 at 21:10
Did you enable it? If you are using gcc or clang you need to compile with
-std=c++17
– NathanOliver
Jun 29 at 21:12
-std=c++17
@NathanOliver Come on,
std::optional
? return "";
is just fine, or better return {};
if your compiler supports this. You're probably outputting the string like std::cout << str << 'n';
, that would print an empty line. You just need to add one if
: if (!str.empty()) std::cout << str << 'n';
.– BJovke
Jun 29 at 21:46
std::optional
return "";
return {};
std::cout << str << 'n';
if
if (!str.empty()) std::cout << str << 'n';
2 Answers
2
If you can compile using C++17 you can use std::optional
to allow you to optionally return something from the function. We would rewrite your function to
std::optional
std::optional<std::string> concat(std::string& x, std::string& y, std::vector<std::string>& vec)
{
if (atoi(x.c_str()) < 0)
{
return {};
}
else
{
std::string concatStr = y + x;
top_back(vec);
top_back(vec);
return concatStr;
}
}
And then in the call site you can use it like
auto ret = concat(some, stuff, here)
if(ret) // only print if ret actually holds a string
std::cout << *ret;
Alternatively you could use a unique_ptr
and return an empty pointer if there is no result. The function would change to
unique_ptr
std::unique_ptr<std::string> concat(std::string& x, std::string& y, std::vector<std::string>& vec)
{
if (atoi(x.c_str()) < 0)
{
return {};
}
else
{
std::string concatStr = y + x;
top_back(vec);
top_back(vec);
return std::make_unique<std::string>(concatStr);
}
}
but the call site would remain the same.
Lastly if a blank string is never going to be a valid return from the function you could just return that and handle it in the call site like
std::string concat(std::string& x, std::string& y, std::vector<std::string>& vec)
{
if (atoi(x.c_str()) < 0)
{
return {};
}
else
{
std::string concatStr = y + x;
top_back(vec);
top_back(vec);
return concatStr;
}
}
int main()
{
//...
auto ret = concat(some, stuff, here)
if(ret != "") // only print if ret actually holds a string
std::cout << ret;
//...
}
What would be the C++11 standard alternative?
– Christian Panov
Jun 29 at 21:14
@IvanStoianov One alternative before
optional
is to return a pointer instead and use dynamic memory. std::unique_ptr
makes that pretty easy and safe.– NathanOliver
Jun 29 at 21:15
optional
std::unique_ptr
This might also be a decent case for
throw
ing an exception if negative numbers are uncommon enough to be called exceptional. Might also be worth looking at using std::stoul
in place of atoi
. Right now atoi
failure is not being checked.– user4581301
Jun 29 at 21:19
throw
std::stoul
atoi
atoi
Thank you very much. Also, just for the record, how do you delete the last line from the console (not in a container or an array)?
– Christian Panov
Jun 29 at 21:27
If you can't use c++17 there is also boost::optional (from which std::optional was taken).
– SoronelHaetir
Jun 29 at 21:28
Because you are not satisfied with C++17 solutions, it is possible to write your own std::optional
implementation.
std::optional
template<typename T>
class Optional
{
bool m_HasValue;
T m_Object;
public:
Optional() : m_HasValue(false){};
Optional(T&& Object) : m_HasValue(true), m_Object(Object){};
operator T&(){return m_Object;}
operator bool(){return m_HasValue;}
T& operator*(){return m_Object;}
};
This is a very simplified version of std::optional
, but it will fulfill your needs.
Its usage remains the same as in this post above.
std::optional
using std::string;
Optional<string> DoSomething(string Input)
{
if(Input == "dontprocessme")
return {}
// ... otherwise process the string
string Output;
// blah blah
return Output;
}
// ...
auto RetString = DoSomething("processme");
if(RetString)
std::cout << *RetString;
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Do you have to use C++11? If you can use C++17 you can use
std::optional
which is made for this use case. If you have to stick with C++11 you could useboost::optional
instead.– NathanOliver
Jun 29 at 21:03