I would like to combine these two functionalities into a single function interface:
T& Transform(T & foo){
//transform t
return t;
}
T As_Transformed(T foo){
//transform t
return t;
}
Sometimes I want to transform a variable passed into the function.
Other times I want a new variable with the applied transformation.
As a result, I end up creating two functions everytime, and following a made up convention of mine where As_
takes and returns a copy, while not having As_
takes and returns a reference.
How can I write a single function implementation that will handle both of these behaviors?
I have no requirements on what it should look like, but I'd like to have a way where I'm not relying on my As_
convention, and ideally where I only make one function instead of two.
Example:
Here is an example of what this would look like.
Let's take Uppercase()
and As_Upercased()
std::string str1 = "hello";
Uppercase(str1); //str is now "HELLO"
std::string str2 = "hello";
auto str3 = As_Uppercased(str2); //str2 is still "hello",
//but str3 is "HELLO"
I don't know what the combined interface would look like, but perhaps:
std::string str1 = "hello";
Uppercase<REF>(str1); //str is now "HELLO"
std::string str2 = "hello";
auto str3 = Uppercase<COPY>(str2); //str2 is still "hello",
//but str3 is "HELLO"
Or maybe I can do something with reference wrappers.
The possible implementations of this, are what I'm asking about.
You can tell the compiler how to differentiate the two by providing an overload on std::reference_wrapper
. Then the code would look like this, for example:
#include <iostream>
#include <functional>
using T = std::string;
T Transform(T t)
{
t += " copy";
return t;
}
std::reference_wrapper<T> Transform(std::reference_wrapper<T> t)
{
t.get() += " ref";
return t;
}
int main()
{
T t{"original"};
std::cout << Transform(Transform(t)) << "\n";
std::cout << t << "\n";
std::cout << Transform(Transform(std::ref(t))).get() << "\n";
std::cout << t;
}
Output:
original copy copy
original
original ref ref
original ref ref
Notice, how the original value is left intact after the first call chain and is modified after the second one.
In your actual code, the first overload would just call the second to transform its passed-by-copy parameter wrapped using std::ref
to avoid code duplication.
LIVE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With