Automatically use const-ref with large parameters

When I have a pseudo-class:

template <class T> class tmplClass { void doSomething(T input); }; 

Is there a way to change void doSomething(T input) to void doSomething(const T& input) when sizeof (T) is larger than the system architecture.

So if you have tmplClass<char> c; for example, use void doSomething(T input) , and when you have tmplClass<[another big class with lots of variables]> use void doSomething(const T& input)

  • Am I getting optimization from this?
  • Is there anything I need to do, or can gcc do it automatically
  • If I need to do something, what?
+4
source share
2 answers

Sure:

 template<typename T, bool=true> struct eff_arg { typedef T type; }; template<typename T> struct eff_arg<T, (sizeof(T)>sizeof(int))> { typedef T const& type; }; // C++11 addition template<typename T> using EffArg = typename eff_arg<T>::type; 

using:

 template <class T> class tmplClass { // C++11 void doSomething(EffArg<T> input); // C++03 void doSomething(typename eff_arg<T>::type input); }; 

and replace sizeof(int) with whatever type you want to use as "the point at which you want to pass the link, not by value."

Note that parameter size is a mediocre way to make this decision: an extremely small class (even smaller than a pointer!) Can have deep copy semantics when a large structure is duplicated when it is duplicated. And often, circumcision does not have to be an int size or a pointer, but more, because indirection has value.

The idea may be to copy only objects that do not manage resources and are small enough. std::is_trivially_copyable<T>::value && (sizeof(T) <= 2*sizeof(void*)) may be the type of check you must do before passing T , not T const& , when you don't need a copy of the data .

This leads to the following:

 template<typename T, bool=true> struct eff_arg { typedef T const& type; }; template<typename T> struct eff_arg<T, std::is_trivially_copyable<T>::value && (sizeof(T)<=2*sizeof(void*)) > { typedef T type; }; template<typename T> using EffArg = typename eff_arg<T>::type; 
+8
source

Yes Easy:

 #include <type_traits> template <typename T> struct Foo { void do_something(typename std::conditional<(sizeof(T) > sizeof(void *)), T const &, T>::type x) { // ... use "x" } // ... }; 

You might want to assign the resulting type to some type alias for easy reuse.

As @Yakk shows, it might be useful to add std::is_trivially_copyable<T>::value to this condition to avoid accidentally copying what is expensive to copy or what might throw.

+8
source

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


All Articles