template pass by value or const reference or...? - c++

I can write a templated function this way
template<class T> void f(T x) {…}
or this way
template<class T> void f(T const& x) {…}
I guess that the second option can be more optimal as it explicitly avoids a copy, but I suspect that it can also fail for some specific types T (eg functors?).
So, when should use the first option, and when to use the second? There are also this boost::call_traits<T>::param_type and boost::reference_wrapper that were in the answers to my previous question, but people don't use them everywhere, do they? Is there a rule of thumb for this? Thanks.

Is there a rule of thumb for this?
The same general rules for when to use pass by reference vs. pass by value apply.
If you expect T always to be a numeric type or a type that is very cheap to copy, then you can take the argument by value. If you are going to make a copy of the argument into a local variable in the function anyway, then you should take it by value to help the compiler elide copies that don't really need to be made.
Otherwise, take the argument by reference. In the case of types that are cheap to copy, it may be more expensive but for other types it will be faster. If you find this is a performance hotspot, you can overload the function for different types of arguments and do the right thing for each of them.

I suspect that it can also fail for some specific types
Pass by reference-to-const is the only passing mechanism that "never" fails. It does not pose any requirements on T, it accepts both lvalues and rvalues as arguments, and it allows implicit conversions.

Thou shalt not wake the dead, but head a similar problem and here's some example code that shows how to use C++11s type traits to deduce whether a parameter should be passed by value or reference:
#include <iostream>
#include <type_traits>
template<typename key_type>
class example
{
using parameter_type = typename std::conditional<std::is_fundamental<key_type>::value, key_type, key_type&>::type;
public:
void function(parameter_type param)
{
if (std::is_reference<parameter_type>::value)
{
std::cout << "passed by reference" << std::endl;
} else {
std::cout << "passed by value" << std::endl;
}
}
};
struct non_fundamental_type
{
int one;
char * two;
};
int main()
{
int one = 1;
non_fundamental_type nft;
example<int>().function(one);
example<non_fundamental_type>().function(nft);
return 0;
}
Hope it helps others with a similar issue.

Besides what James McNellis wrote, I just want to add that you can specialize your template for reference types (for example like this)

boost::traits has a type trait that selects the "best" type, based on T:
call_traits<T>::param_type
As already mentioned, there are no template-specific issues.

Related

Why c++ allows default template argument that can never be used?

If I have a function template that has default argument for its template parameter and that function takes a non-default parameter of the type parameter then what's the point in the language to allow that default argument that'll never be used? :
template <class T = int>
void foo(T x){cout << x << endl;}
int main()
{
foo("hi"); // T is char const *
foo(); // error
}
As you can see T=int can never be used because the function doesn't have a default parameter thus the compiler in this context always deduces the type of T from the argument passed to foo.
But it can be used. Here's an example.
auto* foo_ptr = &foo<>; // The default template argument is used.
A function call expression is not the only context where a function template's arguments need to be figured out.
Although default parameters are usually used for non deduced parameters, taking the address of the function (&foo) uses them too.
Another example:
#include <typeinfo>
#include <iostream>
using namespace std;
template <class T = int>
void coutType() {
cout << typeid(T).name() << endl;
}
int main() {
// default
coutType();
// non-default
coutType<double>();
}
Output with Clang++
int
double
what's the point in the language to allow [X]?
Better: what would be the point in prohibiting [X]?
There is value in simplicity. I would give the burden of proof to the side that wants to make the language more complicated. The language allows a template parameter to have a default value. The language allows a template parameter to be deduced when the function is directly invoked. It is simpler to allow these to co-exist than to add a prohibition against using both. Hence I would ask why prohibit, rather than ask why allow. If there is no compelling reason for the complication, then stick to simple. Being allowed to do something does not force one to do it. And maybe someone (like StoryTeller and Dani) will find a use for that something.
Of course, simplicity is not the ultimate criterion. If harm would come from [X], then that would likely outweigh simplicity concerns. Complications can be justified. However, complications should not be introduced just because something seems useless.
On the other hand, one could reasonably ask if [X] can be put to use. And maybe that was the real question, even if the OP did not realize it. Still, I thought I would put up one answer addressing the question-as-phrased.

C++ When to use const Reference over Forwarding Reference

Consider we need to implement a function f with a templated argument T t. The function should not copy t and accept both rvalues and lvalues, therefore two implementations are possible:
template <class T>
void f(const T& t) { ... }
template <class T>
void f(T&& t) { ... }
If we want to change t inside of f or need to preserve the value category, we have to use the second version. So by this line of thought when and why would we go for the first option?
You'll mainly go for the first option when you want to give strong guarantee to the clients of your function that t won't be changed inside of f. Although you can drop the const qualifier and still not modify t, it's considered good practice and good interface design to qualify as const a parameter if you don't change it's referred to value inside a function, plus it helps the compiler to optimize the code better.
As an extra, know that you can use const_cast to hack around the type safety of const if you really must, but recall that you're doing exactly that: getting rid of the type safety. Avoid this at all cost.
And lastly, a const qualifier doesn't prevent copying, you can easily do something like:
int main()
{
const int a = 3;
int b = a; // a is copied to b
}
In this generic scenario, there is no reason to write both overloads.
If f will only observe its argument, then only the const T& overload is needed.
If f will just forward its argument to some other function, then only the T&& overload is needed, and will use std::forward<T>. (This includes the case where the function needs to retain a copy of the value, i.e., forward it to a copy/move constructor.)

Trailing return type deduced from input arguments concrete use-case

I have seen that one of the always given reasons of using trailing return types is when we want to deduce the return type from the input arguments.
I know there are other reasons but I'm focusing this specific one in this question.
One of the given example is:
template <typename T>
auto func(const T & t) -> decltype(std::cout << t)
{
return std::cout << t;
}
But I could not figure out any concrete use-case of this.
I mean, we always know the return type of a function when we write it, I can't find any concrete example when deducing the return type from arguments is really needed and cannot be avoided.
We can always (if I'm not mistaken) rewrite the function's prototype by directly specifying the return type without any deduction which makes it more concise and clearer in my sense.
The above example can be rewritten as:
template <typename T>
std::ostream& func(const T & t)
{
return std::cout << t;
}
In my opinion, this is less verbose and more readable than the trailing return type version.
What am I missing ?
I mean, we always know the return type of a function when we write it
Do we? So If you write this function template:
template<typename A, typename B>
/* ret */ foo(A a, B b) {
return a + b;
}
You can say for sure what ret is? If given two integer then it's an integer, sure. But if provided an integer and a long, it should be long due to promotions. And if one argument is a double, than the result should be a double two.
And what if that's two objects of some class types? Now we are calling an overloaded operator+, and there's absolutely no guessing what it may return.
I hope your'e convinced now that by saying we accept any two types, we cannot always be sure what is the type of an expression involving those types.
So a mechanism was added to the language to tell. Granted, this example is overly simple and is likely superseded by auto return types, but the general principle remains. When writing generic code, we often deal with unknown types. There is almost no knowing what should be the type of an expression involving them, or even if an expression like that is valid before the function is instantiated. decltype tells us that.
The above example can be rewritten as:
No it cannot. Your conclusion is based on the assumption that there is a:
std::ostream& operator<<(std::ostream&,const T&);
But this need not be the case. It could be a
any_other_type operator<<(std::ostream&,const T&);
Then your version of the method would fail to compile, while the one with deduced return type would be fine.
For a concrete use case, consider some kind of io-manipulation that lets you write code such as
std::cout << all_caps_modifier << "some text" << back_to_normal_modifier << " more text";
That would print:
SOME TEXT more text
I admit this is a rather contrived example, but using some proxy that encapsulates std::cout and makes the string getting printed in capital letters is a possible way to implement it ( std::cout << all_caps_modifier would return a type different from std::ostream&).

std::forward without perfect forwarding?

Advice on std::forward is generally limited to the canonical use case of perfectly forwarding function template arguments; some commentators go so far as to say this is the only valid use of std::forward. But consider code like this:
// Temporarily holds a value of type T, which may be a reference or ordinary
// copyable/movable value.
template <typename T>
class ValueHolder {
public:
ValueHolder(T value)
: value_(std::forward<T>(value)) {
}
T Release() {
T result = std::forward<T>(value_);
return result;
}
private:
~ValueHolder() {}
T value_;
};
In this case, the issue of perfect forwarding does not arise: since this is a class template rather than a function template, client code must explicitly specify T, and can choose whether and how to ref-qualify it. By the same token, the argument to std::forward is not a "universal reference".
Nonetheless, std::forward appears to be a good fit here: we can't just leave it out because it wouldn't work when T is a move-only type, and we can't use std::move because it wouldn't work when T is an lvalue reference type. We could, of course, partially specialize ValueHolder to use direct initialization for references and std::move for values, but this seems like excessive complexity when std::forward does the job. This also seems like a reasonable conceptual match for the meaning of std::forward: we're trying to generically forward something that might or might not be a reference, only we're forwarding it to the caller of a function, rather than to a function we call ourselves.
Is this a sound use of std::forward? Is there any reason to avoid it? If so, what's the preferred alternative?
std::forward is a conditional move-cast (or more technically rvalue cast), nothing more, nothing less. While using it outside of a perfect forwarding context is confusing, it can do the right thing if the same condition on the move applies.
I would be tempted to use a different name, even if only a thin wrapper on forward, but I cannot think of a good one for the above case.
Alternatively make the conditional move more explicit. Ie,
template<bool do_move, typename T>
struct helper {
auto operator()(T&& t) const
-> decltype(std::move(t))
{
return (std::move(t));
}
};
template<typename T>
struct helper<false, T> {
T& operator()(T&& t) const { return t; }
};
template<bool do_move, typename T>
auto conditional_move(T&& t)
->decltype( helper<do_move,T>()(std::forward<T>(t)) )
{
return ( helper<do_move,T>()(std::forward<T>(t)) );
}
that is a noop pass-through if bool is false, and move if true. Then you can make your equivalent-to-std::forward more explicit and less reliant on the user understanding the arcane secrets of C++11 to understand your code.
Use:
std::unique_ptr<int> foo;
std::unique_ptr<int> bar = conditional_move<true>(foo); // compiles
std::unique_ptr<int> baz = conditional_move<false>(foo); // does not compile
On the third hand, the kind of thing you are doing above sort of requires reasonably deep understanding of rvalue and lvalue semantics, so maybe forward is harmless.
This sort of wrapper works as long as it's used properly. std::bind does something similar. But this class also reflects that it is a one-shot functionality when the getter performs a move.
ValueHolder is a misnomer because it explicitly supports references as well, which are the opposite of values. The approach taken by std::bind is to ignore lvalue-ness and apply value semantics. To get a reference, the user applies std::ref. Thus references are modeled by a uniform value-semantic interface. I've used a custom one-shot rref class with bind as well.
There are a couple inconsistencies in the given implementation. The return result; will fail in an rvalue reference specialization because the name result is an lvalue. You need another forward there. Also a const-qualified version of Release, which deletes itself and returns a copy of the stored value, would support the occasional corner case of a const-qualified yet dynamically-allocated object. (Yes, you can delete a const *.)
Also, beware that a bare reference member renders a class non-assignable. std::reference_wrapper works around this as well.
As for use of forward per se, it follows its advertised purpose as long as it's passing some argument reference along according to the type deduced for the original source object. This takes additional footwork presumably in classes not shown. The user shouldn't be writing an explicit template argument… but in the end, it's subjective what is good, merely acceptable, or hackish, as long as there are no bugs.

When should I use forward and move?

I have a code that operates on a vector:
template<typename T>
void doVector(vector<T>& v, T&& value) {
//....
v.push_back(value);
//...
}
For normal push_back, do I need to use forward(value), move(value) or just value (according to new C++11) ? and how do they impact the performance?
For example,
v.push_back(forward<T>(value));
The current code will not compile when the second argument is lvalue because T&& will turn out to be X& which means T needs to be X& which in turn means std::vector<T> will become std::vector<X&> which will NOT match the first argument which is std::vector<X> &. Hence, it is an error.
I would use two template parameters:
template<typename T, typename V>
void doVector(vector<T> & v, V && value)
{
v.emplace_back(std::forward<V>(value));
}
Since V could a different type from T, so emplace_back makes more sense, because not only it solves the problem, it makes the code more generic. :-)
Now the next improvement : since we're using emplace_back which creates the object of type T from argument value (possibly using constructor), we could take advantage of this fact, and make it variadic function:
template<typename T, typename ...V>
void doVector(vector<T> & v, V && ... value)
{
v.emplace_back(std::forward<V>(value)...);
}
That is even more generic, as you could use it as:
struct point
{
point(int, int) {}
};
std::vector<point> pts;
doVector(pts, 1, 2);
std::vector<int> ints;
doVector(ints, 10);
Hope that helps.
forward(value) is used if you need perfect forwarding meaning, preserving things like l-value, r-value.
forwarding is very useful because it can help you avoid writing multiple overloads for functions where there are different combinations of l-val, r-val and reference arguments
move(value) is actually a type of casting operator that casts an l-value to an r-value
In terms of performances both avoid making extra copies of objects which is the main benefit.
So they really do two different things
When you say normal push_back, I'm not sure what you mean, here are the two signatures.
void push_back( const T& value );
void push_back( T&& value );
the first one you can just pass any normal l-val, but for the second you would have to "move" an l-val or forward an r-val. Keep in mind once you move the l-val you cannot use it
For a bonus here is a resource that seems to explain the concept of r-val-refs and other concepts associated with them very well.
As others have suggested you could also switch to using emplace back since it actually perfect forwards the arguments to the constructor of the objects meaning you can pass it whatever you want.
When passing a parameter that's a forwarding reference, always use std::forward.
When passing a parameter that's an r-value, use std::move.
E.g.
template <typename T>
void funcA(T&& t) {
funcC(std::forward<T>(t)); // T is deduced and therefore T&& means forward-ref.
}
void funcB(Foo&& f) {
funcC(std::move(f)); // f is r-value, use move.
}
Here's an excellent video by Scott Meyers explaining forwarding references (which he calls universal references) and when to use perfect forwarding and/or std::move:
C++ and Beyond 2012: Scott Meyers - Universal References in C++11
Also see this related question for more info about using std::forward: Advantages of using forward
http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Scott-Meyers-Universal-References-in-Cpp11
That video, IMO, has the best explanation of when to use std::forward and when to use std::move. It presents the idea of a Universal Reference which is IMO an extremely useful tool for reasoning about move semantics.