автоматически использовать const-ref по большим параметрам

Когда у меня есть следующий псевдокласс:

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

Есть ли способ изменить void doSomething(T input) в void doSomething(const T& input) когда sizeof (T) больше, то архитектура системы.

Значит, когда у вас есть tmplClass<char> c; например, использовать void doSomething(T input) и когда у вас есть tmplClass<[another big class with lots of variables]> использование void doSomething(const T& input)

  1. Получу ли я какую-либо оптимизацию от этого?
  2. Есть ли что-нибудь, что я должен сделать, или gcc может сделать это автоматически
  3. Если я должен что-то сделать, что?

4

Решение

Конечно:

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;

использовать:

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

и заменить sizeof(int) с любым типом, который вы хотите использовать в качестве «точки, где вы хотите передать в качестве ссылки, а не по значению».

Обратите внимание, что размер параметра — посредственный способ принять это решение: очень маленький класс (даже меньше, чем указатель!) Может иметь глубокую семантику копирования, где большая структура дублируется при дублировании. И часто отрезок не должен быть размером int или указатель, но больше, чем это, потому что косвенное обращение имеет цену.

Идея может заключаться в том, чтобы копировать только объекты, которые не управляют ресурсами и являются достаточно маленькими. std::is_trivially_copyable<T>::value && (sizeof(T) <= 2*sizeof(void*)) может быть вид проверки, которую вы должны сделать перед прохождением T а не T const& когда вам не нужно копировать данные.

Это приводит к следующему:

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

Другие решения

Да легко

#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"}

// ...
};

Возможно, вы захотите присвоить результирующий тип псевдониму некоторого типа для легкого повторного использования.

Как подсказывает @Yakk, было бы неплохо добавить std::is_trivially_copyable<T>::value к условию, чтобы избежать случайного копирования чего-то дорогого, чтобы скопировать или что может бросить.

8

По вопросам рекламы [email protected]