I'm writing a library which does numeric computations. I'm using templates so that the end-user can pick the precision they want. I would like this to work both with fundamental types (double, float) and high precision class types (e.g. boost::multiprecision). I'm wondering then if the argument types should be T or const & T.
On SO/google there are many posts about passing by value vs by reference. One of the "rules-of-thumb" seems to be:
- Pass fundamental types by value
- Pass everything else by const reference
However, this gets muddy if you have a template:
template<typename T>
T doSomething(T x, T y)
{
return x + y;
}
vs.
template<typename T>
T doSomething(const T & x, const T & y)
{
return x + y;
}
For boost::multiprecision you almost certainly want to pass by const reference. The question is whether passing double by const & is worse than by value. Many SO answers say const & is "no better and maybe worse"...but I couldn't find any good hard references.
I did the following benchmark
which seems to indicate there's no difference although maybe it depends on the simplicity of the function and inlining behavior.
There's the possibility of doing something like:
#include <type_traits>
template<typename T>
using choose_arg_type =
typename std::conditional<std::is_fundamental<T>::value,
T,
const T &>::type;
template <typename T>
T someFunc(choose_arg_type<T> arg)
{
return arg + arg;
}
int main()
{
auto result = someFunc<double>(0.0);
return 0;
}
But if it brings no benefit, it's added complexity and you lose type deduction (Any way to fix this type deduction?)
One reason I can think that pass by const reference is slower is, if it truly is using a reference, there may be cache locality issues. But if the compiler just optimizes to value...this won't matter.
What's the best way to handle this?