Reputation: 443
I have a template function, that accepts a read-only parameter of the templated type. This is a library function for various platforms, from 8-bit (AVR8) to 32 bit (Cortex). How to pass this parameter?
template< typename T >
void f( const T p ){ ... }
template< typename T >
void f( const T & p ){ ... }
By value is (probably) more efficient for parameter types that are smaller than a pointer, by reference is (probably) more efficient for parameter types that are larger than a pointer, and/or expensive to copy.
Is there any standard way to abstract this choice, like
template< typename T >
void f( pass_efficiently< T > p ){ ... }
?
Upvotes: 4
Views: 1089
Reputation: 1300
Expanding from Bryan's answer and your additional question, hopefully to make it clear:
You can compose a type trait using Bryan's information and, if you want, the size. For this example, I'm using std::is_trivially_copyable
and an implementation-defined maximum size:
template <typename T>
inline constexpr bool is_efficiently_copyable_v =
std::is_trivially_copyable_v<T> && (sizeof(T) <= magic_size);
Then, you can use this trait to define which function to use with SFINAE (or concepts in C++20), making them mutually exclusive:
template <typename T>
auto f(const T&) -> std::enable_if_t<!is_efficiently_copyable_v<T>>;
template <typename T>
auto f(T) -> std::enable_if_t<is_efficiently_copyable_v<T>>;
(You can also use any other flavor of SFINAE you want)
This way, your function f
's interface always receives the parameter in your desired way. Live example: Notice which functions are called in the assembly output.
Just a small side note: GCC generates the same code for const T&
and T
parameters in all architectures I tested, but Clang doesn't, so beware of that if you just want to go the const reference route. Live example: you may change the parameter type in the main
function and between compilers to verify this.
Upvotes: 0
Reputation: 441
You can use std::is_fundamental
to check if the value is a built in type and overload/specialize to pass by value if true.
There are more things to specialize for using the type support library <type_traits>
such as is_enum
, is_trivially_copyable
, is_array
and many more. I would recommend checking it out and seeing what works best for you.
Reference link for std::is_fundamental
:
https://en.cppreference.com/w/cpp/types/is_fundamental
Reference link for <type_traits>
:
https://en.cppreference.com/w/cpp/header/type_traits
Upvotes: 3