大形参自动使用const-ref

automatically use const-ref by big parameters

本文关键字:const-ref 形参      更新时间:2023-10-16

当我有以下伪类:

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

当sizeof(T)大于系统架构时,是否有办法将void doSomething(T input)改为void doSomething(const T& input) ?

意味着,例如当你有tmplClass<char> c;时,使用void doSomething(T input),当你有tmplClass<[another big class with lots of variables]>时,使用void doSomething(const T& input)

  1. 我能从中得到任何优化吗?
  2. 有什么我必须做的,或者gcc可以自动完成
  3. 如果我必须做什么,什么?

当然:

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或指针的大小,而应该大于它们,因为间接操作有代价。

一个想法可能是只复制那些不管理资源并且足够小的对象。当您不需要数据的副本时,在通过T而不是T const&之前应该进行std::is_trivially_copyable<T>::value && (sizeof(T) <= 2*sizeof(void*))检查。

结果如下:

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;

很简单:

#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也添加到条件中可能是好的,以避免意外地复制昂贵的复制或可能抛出的内容。