2009-07-22 75 views
4

据我所知,传递一个目的是一个函数,它比一个寄存器更大时,这是优选将其传递作为(常数)参考,例如:如何使用模板来确定适当的参数传递方法?

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

这避免了必须执行可能昂贵拷贝的论点。

然而,通过适合到寄存器中,将它作为一个(常量)参考充其量是多余的,在最坏的情况要慢类型时:

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是一个有趣的心理练习。

+0

刚一说明,(不是一个真正的直接回答你的问题),我想你会需要使用类型名称是这样的:`void bar(typename const_nocopy :: type baz);` – 2009-07-22 20:31:25

+2

你真的需要解决这个问题吗? – 2009-07-22 20:37:41

+3

'我们如何说服人们,在编程简单和清晰度方面 - 简言之:数学家称之为“优雅” - 不是可有可无的奢侈品,而是决定成败之间的关键问题? --Edsger Dijkstra – 2009-07-22 20:38:22

回答

11

使用Boost.CallTraits

#include <boost/call_traits.hpp> 

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

如果变量的拷贝时间很长,编译器可能会内联这个模板的实例,而const引用的东西将会同样有效。

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

只是专门为所有nocopy类型的no_copy<T>模板。

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

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

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

1

第一:使用const & - 如果实现是到大被内联时,cosnt &与争论没有太大的差别了。

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

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);