通过大参数自动使用const-ref

Uro*_*327 4 c++ templates const-reference

当我有下面的伪类:

template <class T> class tmplClass
{
    void doSomething(T input);
};
Run Code Online (Sandbox Code Playgroud)

有一种方法来改变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. 如果我必须做某事,那又怎样?

Ker*_* SB 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"
    }

    // ...
};
Run Code Online (Sandbox Code Playgroud)

您可能希望将结果类型分配给某些类型别名,以便于重用.

正如@Yakk建议的那样,也可以添加std::is_trivially_copyable<T>::value条件以避免意外复制复制或可能丢弃的东西.

  • 在C++ 11中输入别名:`template <typename T>使用EffArg = typename std :: conditional <(sizeof(T)> sizeof(void*)),T const&,T> :: type`,然后使用`EffArg <T>`因为你的"可能是`T`,可能是`T const&`,取决于`T`有多大"类型. (3认同)

Yak*_*ont 8

当然:

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;
Run Code Online (Sandbox Code Playgroud)

使用:

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

并替换sizeof(int)为您要用作"要作为参考而不是按值传递的点"的任何类型.

请注意,参数的大小是做出此决定的平庸方式:极小的类(甚至小于指针!)可能具有深层复制语义,其中大型结构在复制时会重复.通常情况下,截止不应该是int指针的大小或指针,而应该大于指针的大小,因为间接成本是有代价的.

一个想法可能是仅复制不管理资源且足够小的对象. std::is_trivially_copyable<T>::value && (sizeof(T) <= 2*sizeof(void*))可能是在传递a之前应该进行的检查,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;
Run Code Online (Sandbox Code Playgroud)