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 "";





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 use boost::optional instead.
– NathanOliver
Jun 29 at 21:03


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 throwing 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.

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

Opening a url is failing in Swift

Export result set on Dbeaver to CSV