如何使用模板来确定适当的参数传递方法?

时间:2009-07-22 20:16:14

标签: c++ templates typetraits

据我所知,当一个对象传递给一个比寄存器大的函数时,最好把它作为(const)引用传递给它,例如:

void foo(const std::string& bar)
{
    ...
}

这避免了必须执行可能昂贵的参数副本。

但是,当传递一个适合寄存器的类型时,将它作为(const)引用传递最多是冗余的,最糟糕的是:

void foo(const int& bar)
{
    ...
}

我的问题是,当我使用需要传递任何类型的模板类时,我想知道如何充分利用这两个世界:

template <typename T>
class Foo
{
  public:

    // Good for complex types, bad for small types
    void bar(const T& baz);   

    // Good for small types, but will needlessly copy complex types
    void bar2(T baz);             
};

是否有模板决策方法允许我选择正确的类型?可以让我做的事情,

void bar(const_nocopy<T>::type baz);

根据类型选择更好的方法?


修改

经过大量的定时测试后,两个通话时间之间的差异是不同的,但非常小。对于我的情况,解决方案可能是一个可疑的微优化。尽管如此,TMP仍然是一项有趣的心理锻炼。

4 个答案:

答案 0 :(得分:11)

使用Boost.CallTraits

#include <boost/call_traits.hpp>

template <typename T>
void most_efficient( boost::call_traits<T>::param_type t ) {
    // use 't'
}

答案 1 :(得分:6)

如果变量复制时间很重要,编译器可能会内联该模板的实例,并且const引用也同样有效。

从技术上讲,你已经给了自己一个答案。

只需为所有nocopy类型专门设置no_copy<T>模板。

template <class T> struct no_copy { typedef const T& type; };

template <> struct no_copy<int> { typedef int type; };

答案 2 :(得分:1)

我能想到的唯一解决方案是使用宏为较小的类生成专用模板版本。

答案 3 :(得分:1)

首先:使用const & - 如果要实现的内容很大,那么cosnt&amp;与论证不再有太大区别。

第二:这是我能想到的最好的。无法正常工作,因为编译器无法推断出参数类型

template <typename T, bool UseRef> 
struct ArgTypeProvider {};

template <typename T>
struct ArgTypeProvider<T, true>
{
   typedef T const & ArgType;
};

template <typename T>
struct ArgTypeProvider<T, false>
{
   typedef T ArgType;
};

template <typename T>
struct ArgTypeProvider2 : public ArgTypeProvider<T, (sizeof(T)>sizeof(long)) >
{
};

// ----- example function
template <typename T>
void Foo(typename ArgTypeProvider2<T>::ArgType arg)
{
   cout << arg;
}

// ----- use
std::string s="fdsfsfsd";
// doesn't work :-(
// Foo(7);
// Foo(s);

// works :-)
Foo<int>(7);
Foo<std::string>(s);