Reputation: 4283
I seem to remember I way to select value-pass or reference-pass of a parameter using the size of the type.
Something like:
void fun( check<A> a ){
...
}
Generates or:
void fun( A a ){
...
}
or
void fun( A & a ){
...
}
Depending of the size of type A and the architecture where you compile the applicacion.
Upvotes: 6
Views: 605
Reputation: 9089
In C++11 you can use std::conditional
:
#include <type_traits>
class A { ... };
typedef std::conditional<
std::is_trivially_copyable<A>::value && sizeof(A) <= sizeof(int),
A, const A&>::type AParam;
// Direct usage
void f(AParam param);
// Wrap into template class
template <typename T> struct check:
std::conditional<std::is_arithmetic<T>::value, T, const T&> {};
void f(check<A>::type param);
For C++03 compilers you could use Boost implementation - Boost.TypeTraits library.
As @sehe mentioned there is also Boost.CallTraits library that correctly implements required functionality:
#include <boost/call_traits.hpp>
class A { ... };
void f(boost::call_traits<A>::param_type param);
Upvotes: 13
Reputation: 393084
What you describe doesn't directly exist (at least, not standard)
Edit Found what the OP was probably reffering to:
call_traits<T>::param_type
is likely what the Op had in mind/remembered:
template<typename T>
using check = typename boost::call_traits<T>::param_type;
void f(check<A> param);
Defines a type that represents the "best" way to pass a parameter of type T to a function.
Examples
The following table shows the effect that call_traits has on various types, the table assumes that the compiler supports partial specialization: if it doesn't then all types behave in the same way as the entry for "myclass", and call_traits can not be used with reference or array types.
You could be referring to two three things, AFAICT:
rvalue
referencesI can imagine you mean that you could optimize for move semantics. E.g.:
struct Demo
{
Demo(std::string&& tomove) : _s(std::move(tomove)) { }
private:
std::string _s;
};
This way,
std::string a_very_large_string;
Demo moving(std::move(a_very_large_string)); // prevents a copy
Perfect forwarding is the same principle applied to generic situations:
#include <tuple>
#include <string>
#include <vector>
typedef unsigned int uint;
template <typename... T>
void AnotherDemo(T... args)
{
std::tuple<T...> perfect(std::forward<T>(args)...); // optimal
// more code using perfect, passing it by reference etc.
}
int main(int argc, const char *argv[])
{
AnotherDemo(std::string("moved")); // moved
AnotherDemo(42); // copied
std::vector<double> v { 1,2,3 };
AnotherDemo(v); // copied
AnotherDemo(std::move(v)); // moved
}
Building on @Rost's answer, you could use meta programming to achieve this:
E.g. using a template alias:
#include <type_traits>
template<typename T>
using check = typename boost::call_traits<T>::param_type;
void f(check<A> param);
Upvotes: 6