How to create a C ++ template to convey the value in the best way?

I seem to remember how I selected the value-pass or reference-pass of the parameter using the size of this type.

Sort of:

void fun( check<A> a ){ ... } 

Creates or:

 void fun( A a ){ ... } 

or

 void fun( A & a ){ ... } 

Depending on the size of type A and the architecture in which you are compiling the expression.

+6
source share
2 answers

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 can use the Boost implementation - Boost.TypeTraits library .

As mentioned above, there is also a Boost.CallTraits library that correctly implements the necessary functions:

 #include <boost/call_traits.hpp> class A { ... }; void f(boost::call_traits<A>::param_type param); 
+12
source

What you describe does not directly exist (at least not standard)

Change It is determined that the OP probably repeated:

0. Boost Call Features

call_traits<T>::param_type , probably that remembered or remembered Op:

 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.

<strong> Examples

The following table shows that call_traits has different types, the table assumes that the compiler supports partial specialization: if this is not the case, all types behave the same as the entry for "myclass", and call_traits may not be used with references or array types . enter image description here

You can refer to two three things: AFAICT:

1. rvalue links

I can imagine that you mean that you can optimize the semantics of movement. For instance:.

 struct Demo { Demo(std::string&& tomove) : _s(std::move(tomove)) { } private: std::string _s; }; 

Thus,

  std::string a_very_large_string; Demo moving(std::move(a_very_large_string)); // prevents a copy 

2. Perfect shipment:

Perfect forwarding is the same principle that applies to general 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 } 

3. Meta programming:

Based on @Rost's answer, you can use metaprogramming to achieve this:

eg. using the template alias:

 #include <type_traits> template<typename T> using check = typename boost::call_traits<T>::param_type; void f(check<A> param); 
+5
source

Source: https://habr.com/ru/post/927053/


All Articles