Is there a way to make a function have different behavior if its return value will be used as an rvalue reference instead of an lvalue? - c++

I have a routine that does some moderately expensive operations, and the client could consume the result as either a string, integer, or a number of other data types. I have a public data type that is a wrapper around an internal data type. My public class looks something like this:
class Result {
public:
static Result compute(/* args */) {
Result result;
result.fData = new ExpensiveInternalObject(/* args */);
return result;
}
// ... constructors, destructor, assignment operators ...
std::string toString() const { return fData->toString(); }
int32_t toInteger() const { return fData->toInteger(); }
double toDouble() const { return fData->toDouble(); }
private:
ExpensiveInternalObject* fData;
}
If you want the string, you can use it like this:
// Example A
std::string resultString = Result::compute(/*...*/).toString();
If you want more than one of the return types, you do it like this:
// Example B
Result result = Result::compute(/*...*/);
std::string resultString = result.toString();
int32_t resultInteger = result.toInteger();
Everything works.
However, I want to modify this class such that there is no need to allocate memory on the heap if the user needs only one of the result types. For example, I want Example A to essentially do the equivalent of,
auto result = ExpensiveInternalObject(/* args */);
std::string resultString = result.toString();
I've thought about structuring the code such that the args are saved into the instance of Result, make the ExpensiveInternalObject not be calculated until the terminal functions (toString/toInteger/toDouble), and overload the terminal functions with rvalue reference qualifiers, like this:
class Result {
// ...
std::string toString() const & {
if (fData == nullptr) {
const_cast<Result*>(this)->fData = new ExpensiveInternalObject(/*...*/);
}
return fData->toString();
}
std::string toString() && {
auto result = ExpensiveInternalObject(/*...*/);
return result.toString();
}
// ...
}
Although this avoids the heap allocation for the Example A call site, the problem with this approach is that you have to start thinking about thread safety issues. You'd probably want to make fData an std::atomic, which adds overhead to the Example B call site.
Another option would be to make two versions of compute() under different names, one for the Example A use case and one for the Example B use case, but this isn't very friendly to the user of the API, because now they have to study which version of the method to use, and they will get poor performance if they choose the wrong one.
I can't make ExpensiveInternalObject a value field inside Result (as opposed to a pointer) because doing so would require exposing too many internals in the public header file.
Is there a way to make the first function, compute(), know whether its return value is going to become an rvalue reference or whether it is going to become an lvalue, and have different behavior for each case?

You can achieve the syntax you asked for using a kind of proxy object.
Instead of a Result, Result::compute could return an object that represents a promise of a Result. This Promise object could have a conversion operator that implicitly converts to a Result so that "Example B" still works as before. But the promise could also have its own toString(), toInteger(), ... member functions for "Example A":
class Result {
public:
class Promise {
private:
// args
public:
std::string toString() const {
auto result = ExpensiveInternalObject(/* args */);
return result.toString();
}
operator Result() {
Result result;
result.fData = new ExpensiveInternalObject(/* args */);
return result;
}
};
// ...
};
Live demo.
This approach has its downsides though. For example, what if, instead you wrote:
auto result = Result::compute(/*...*/);
std::string resultString = result.toString();
int32_t resultInteger = result.toInteger();
result is now not of Result type but actually a Result::Promise and you end up computing ExpensiveInternalObject twice! You can at least make this to fail to compile by adding an rvalue reference qualifier to the toString(), toInteger(), ... member functions on Result::Promise but it is not ideal.

Considering you can't overload a function by its return type, and you wanted to avoid making two different versions of compute(), the only thing I can think of is setting a flag in the copy constructor of Result. This could work with your particular example, but not in general. For example, it won't work if you're taking a reference, which you can't disallow.

Related

Is there a less verbose idiom for unpacking an optional in C++?

In the project I am currently working on I find myself writing a lot of code that looks like the following, where, get_optional_foo is returning an std::optional:
//...
auto maybe_foo = get_optional_foo(quux, ...)
if (!maybe_foo.has_value())
return {};
auto foo = maybe_foo.value()
//...
// continue on, doing things with foo...
I want to bail out of the function if I get a null option; otherwise, I want to assign a non-optional variable to the value. I've started using the convention of naming the optional with a maybe_ prefix but am wondering if there is some way of doing this such that I don't need to use a temporary for the optional at all? This variable is only ever going to be used to check for a null option and dereference if there is a value.
You don't need an intermediate object. std::optional supports a pointer interface to access it so you can just use it like:
//...
auto foo = get_optional_foo(quux, ...)
if (!foo)
return {};
//...
foo->some_member;
(*foo).some_member;
Slightly different than what you are asking, but consider:
if (auto foo = get_optional_foo(1)) {
// ...
return foo->x;
} else {
return {};
}
This places the main body of the function in an if() block, which may be more readable.
Shortest I can think of:
auto maybe_foo = get_optional_foo(quux, ...)
if (!maybe_foo) return {};
auto &foo = *maybe_foo; // alternatively, use `*maybe_foo` below
If you have multiple optionals in the function and it's very unlikely they'll be empty you can wrap the whole thing with a try - catch.
try {
auto &foo = get_optional_foo(quux, ...).value();
auto &bar = get_optional_bar(...).value();
...
} catch (std::bad_optional_access &e) {
return {};
}

Reuse of variable of type auto

I have a special class to be used as return type of methods, containing the wanted value or in case of failure an error message which is even cascading from earlier errors. It works as expected.
As the returned type is differently complex I like to use the keyword auto. But when using a lot of methods I have to create new return variables.
A typical part of code looks like this:
auto ret1 = methodA();
if(ret1.isValid()...
auto ret2 = methodB();
if(ret2.isValid()...
I dont like to always create a new variable. But I like the elegant way of error handling. Using a more dump return type like an error code in integer would solve the problem but then I have no benefit from the error handling return type.
Is there any trick to reuse the first return variable ret1?
You would have to create new scopes to reuse the variable name for a different variable, like:
{
auto ret = methodA();
if (ret.isValid()) ...
}
{
auto ret = methodB();
if (ret.isValid()) ...
}
You can also take advantage of the scope created by if, placing the init-statement inside:
if (auto ret = methodA(); ret.isValid()) ...
if (auto ret = methodB(); ret.isValid()) ...
auto is not a type.
It is a keyword, that says "put the type here for me, by deducing it from the initial value". That occurs during compilation, once.
You cannot reuse ret1 to store an object of a different type, whether you use auto or not.
This shouldn't really be a problem. If you're concerned about "running out of names", or "having many similar names", your names are not descriptive enough and/or your scopes aren't tight enough.
auto is not a type. In auto foo = bar(); the compiler simply figures out what type bar() actually returns and substitutes that in. So if bar() returns int then that's the type of foo, if it returns bool then that is the type of foo. And once the type that auto should be replaced with (the first time) has been determined, then it can never change. auto doesn't mean "variable type" it just means "hey compiler, I'm too lazy to figure out the type to put here, please do it for me", but there is no difference what-so-ever compared to you just writing the final type yourself.
So, you can reuse the variable if what you assign to it the second time is of the same type as the first time - otherwise not.
I dont like to always create a new variable.
Much better is to create a const variable:
const auto ret1 = methodA();
if(ret1.isValid()...
const auto ret2 = methodB();
if(ret2.isValid()...
In this case you need to make const all the methods like isValid, but that is even better: "is" shouldn't have side effects and modify the state.
Next step is to remove the temp variable at all:
if(methodA().isValid()) {
...
}
if(methodB().isValid()) {
...
}
The alternative is to wrap each function call into a block:
{
const auto ret = methodA();
if(ret.isValid()...
}
{
const auto ret = methodB();
if(ret.isValid()...
}
This allows you to reuse the const variable name.
Each block becomes a candidate for extraction into a separate function (see Uncle Bob in "Clean Code").

Avoid a call to a function that may throw in a destructor

I have a ODBC wrapper interface that enables me to execute SQL queries in C++. In particular, I use
the named parameter idiom for
the select statements, for example:
Table.Select("foo").GroupBy("bar").OrderBy("baz");
To achieve this effect, the class Table_t returns a proxy object Select_t:
class Table_t
{
// ...
public:
Select_t Select(std::string const &Stmt)
{ return {*this, Stmt}; }
void Execute(std::string const &Stmt);
};
Select_t combines the basic statement with the additional clauses and executes the actual statement in the destructor:
class Select_t
{
private:
Table_t &Table;
std::string SelectStmt,
OrderStmt,
GroupStmt;
public:
Select_t(Table_t &Table_, std::string const &SelectStmt) :
Table(Table_), SelectStmt(SelectStmt_) {}
~Select_t()
{ /* Combine the statements */ Table.Execute(/* Combined statement */); }
Select_t &OrderBy(std::string const &OrderStmt_)
{ OrderStmt = OrderStmt_; return *this; }
Select_t &GroupBy(std::string const &GroupStmt_)
{ GroupStmt = GroupStmt_; return *this; }
};
The problem is that Table.Execute(Stmt) may throw and I must not throw in a destructor. Is there a
way I can work around that while retaining the named parameter idiom?
So far the only idea I came up with is to add an Execute function to Select_t, but I would prefer not to:
Table.Select("foo").GroupBy("bar").OrderBy("baz").Execute();
Throwing "inside" a destructor is not a problem; the problem is exceptions escaping from a destructor. You need to catch the ODBC exception, and decide how to communicate the error by another interface.
Actually, separating the concerns of the query object and its execution might be a good idea.
Lazy invocation can be very useful.
The Execute function could reasonably be a free function.
For example:
auto myquery = Table.Select("foo").GroupBy("bar").OrderBy("baz");
auto future_result = marshal_to_background_thread(myquery);
//or
auto result = Execute(myquery);
This would lend itself to re-use with respect to prepared statements.
e.g.
auto myquery = Prepare(Table.Select("foo").Where(Equals("name", Param(1))).OrderBy("baz"));
auto result = Execute(myquery, {1, "bob"});
result = Execute(myquery, {1, "alice"});

How to elegantly implement single methods with variable output?

I am trying to improve my code style.
Sometimes I have methods that do complicated checks or computations and depending on the context of the calling method I need different results from these algorithms. Let's assume that there is one result, that is always needed and it will be the return value of the method. But how to deal with the optional other results? Of course I want to implement my complicated method only once. Therefore I have introduced modifiable reference parameters and depending on some conditions they are overwritten with these additional results.
As a convenience for those contexts where I don't need the additional results, I have introduced overloads that create dummy variables that are passed to the single implementation.
Please see the following simplified example code:
#include <iostream>
/**
* \brief Checks whether everything is okay.
*
* \param isCheckedFirstTime if point is not null, it will be overwritten with
* whether this method has been called for the first time
*
* \returns okay or not
*/
bool isOkay(bool*& isCheckedFirstTime)
{
static bool isFirstTime = true;
if (nullptr != isCheckedFirstTime)
{
*isCheckedFirstTime = isFirstTime;
}
isFirstTime = false;
return true;
}
/**
* \brief Checks whether everything is okay.
*
* \returns okay or not
*/
bool isOkay()
{
bool* dummy = nullptr;
return isOkay(dummy);
}
int main()
{
const bool okay = isOkay();
std::cout << "Is everything okay?: " << okay << std::endl;
return 0;
}
Obviously I could get rid of a lot of boilerplate code by adding a default value for the parameter isCheckedFirstTime like this
bool isOkay(bool*& isCheckedFirstTime = nullptr)
which is not legal, because I cannot bind a non-const lvalue reference to an rvalue of the corresponding type.
Is there a workaround for that? Or is there another possibility to have only one method doing all the computations without overloads for different outputs and without having to declare dummy paramters in the calling code?
One solution I could think of is packing all possible results into one std::tuple. Then the caller can use what he wants. But it might have a disadvantage, if calculation of optional results is costly. Then having a condition (like nullptr != ...) saves computation time if nobody needs the result.
I am looking forward to your proposals!
Usually this is done by returning std::tuple.
In your case it will look something like:
std::tuple<bool,bool> isOkay()
{
static bool isFirstTime = true;
bool isCheckedFirstTime = isFirstTime;
isFirstTime = false;
return std::make_tuple(true, isCheckedFirstTime);
}
In case when you need to return optional complex object or you don't want to calculate unneeded value, it's better to use std::optional if you can use C++17.
std::tuple<bool,std::optional<bool>> isOkay(bool needCheckFirstTime = false)
{
static bool isFirstTime = true;
std::optional<bool> isCheckedFirstTime;
if (needCheckFirstTime) {
isCheckedFirstTime = isFirstTime;
}
isFirstTime = false;
return std::make_tuple(true, isCheckedFirstTime);
}
Therefore I have introduced modifiable reference parameters and depending on some conditions they are overwritten with these additional results.
Out parameters should be avoided like plague. If a function produces a result, it should be a part of its return type. So how we figure out such type for your case?
You've suggested a tuple; in this case, a struct or a tuple would work well.
But it might have a disadvantage, if calculation of optional results is costly.
Sure, but there's nothing that says you have to necessarily tie the arguments to the results. A function could take a bitset or similar enumeration telling it exactly what to compute, and return a struct full of optional values. The specific will largely depend on the specific case being solved.
It appears that you're in doubt whether isCheckedFirstTime should be a pointer or a reference, so you made it both. That's just inconvenient.
This might be more expressive:
bool isOkay(std::optional<bool>& isCheckedFirstTime)
{
static bool isFirstTime = true;
if (isCheckedFirstTime)
{
*isCheckedFirstTime = isFirstTime;
}
isFirstTime = false;
return true;
}
bool isOkay()
{
std::optional<bool> dummy;
return isOkay(dummy);
}

Function Return Type: Pointer, Reference or something else?

Let us assume I always need the direkt return type of the function to be of a errorcode (success of calculation or failure) , then I will return some arguments as parameters. Is it better to define them as reference (and create them before empty) or better to return pointer?
Edit: I should be more precise: The errorcode is obligatory because I have to stick to the coding guidline given.
Possibility A:
ErrorCode func( some_parameters ... , ReturnType & result)
...
ReturnType result; // empty constructor, probably not good practice
func( some_parameters ..., result)
Possibility B:
ErrorCode func( some_parameters ... , ReturnType * result){
...
result = new ReturnType(...)
...
}
...
ReturnType * result; // void pointer
func( some_parameters ..., result)
...
delete result; // this is needed if I do not use a smart pointer
Even better: Maybe you have a more appropriate solution?
Edit: Please indicate which standard you are using, since unfortunatelly (guidelines) I have to stick to C++98.
I would do the following (and in general do)
1.) throw an exception instead of returning error codes
if this is not possible (for any reason)
2.) return the pointer directly (either raw or std::unique_ptr) and return nullptr for failure
if return type has to be bool or not all objects returned are (pointers / heap allocated)
3.) return your error code (bool or enum class) and accept a reference parameter for all objects that are to be initialized (must have objects so to speak) and pointers to objects that may be optionally created / initialized
if the object cannot be created in advance to the call (e.g. because it is not default constructible)
4.) pass a reference to a pointer (raw or std::unique_ptr) or a pointer to a pointer, which will then be filled by the function
std::optional (or similar) may be an option if you only have a true/false return code.
I don't like returning std::pair or std::tuple because it can make your code look quite annoying if you have to start using .first/.second or std::get<>() to access your different return types. Using std::tie() can reduce this a little bit, but it is not (yet) very comfortable to use and prevents the use of const.
Examples:
std::unique_ptr<MyClass> func1() { /* ... */ throw MyException("..."); }
std::unique_ptr<MyClass> func2() { /* ... */ }
ErrorCode func3(MyClass& obj, std::string* info = nullptr) { /* ... */ }
ErrorCode func4(std::unique_ptr<MyClass>& obj) { /* ... */ }
int main()
{
try
{
auto myObj1 = func1();
// use ...
}
catch(const MyException& e)
{
// handle error ...
}
if(auto myObj2 = func2())
{
// use ...
}
MyClass myObj3;
std::string info;
ErrorCode error = func3(myObj3, &info);
if(error == ErrorCode::NoError)
{
// use ...
}
std::unique_ptr<MyClass> myObj4;
ErrorCode error = func4(myObj4);
if(error == ErrorCode::NoError)
{
// use ...
}
}
Edit: And in general it is advisable to keep your API consistent, so if you already have a medium or large codebase, which makes use of one or the other strategy you should stick to that (if you do not have good reasons not to).
This is a typical example for std::optional. Sadly it isn't available yet, so you want to use boost::optional.
This is assuming that the result is always either "success with result" or "fail without result". If your result code is more complicated you can return
std::pair<ResultCode, std::optional<ReturnType>>.
It would be good style to to use the return value for all return information. For example:
std::tuple<bool, ReturnType> func(input_args....)
Alternatively, the return type could be std::optional (or its precursor) if the status code is boolean, with an empty optional indicating that the function failed.
However, if the calculation is supposed to normally succeed, and only fail in rare circumstances, it would be better style to just return ReturnType, and throw an exception to indicate failure.
Code is much easier to read when it doesn't have error-checking on every single return value; but to be robust code those errors do need to be checked somewhere or other. Exceptions let you handle a range of exceptional conditions in a single place.
Don't know if it's applicable in your situation but if you have only two state return type then maybe just return pointer from your function and then test if it is nullptr?