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

时间:2013-05-15 20:51:29

标签: c++ templates const-reference

当我有以下伪类时:

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. 如果我必须做某事,那该怎么办?

2 个答案:

答案 0 :(得分: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以避免意外复制复制或可能会丢失的内容。

答案 1 :(得分: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;

使用:

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;