2014-02-09 53 views
1

我有一个模板函数负责将模板值写入流中。它看起来像这样:模板函数:混合通过复制和传递参考

template < typename T > 
void Write(T value, std::ostream& stream, endianness_t endian); 

我已经实现了版本基本类型:INT,UINT,float等 现在,如果我想编写一个更复杂的结构,也就是说,一个的std :: string,我声明如下:

template<> 
inline void Write(const std::string& value, std::ostream& stream, endianness_t endian) { // Notice the reference 
... 
} 

,而无需调用显式调用“传递按引用”的版本,我不能把它叫做:

Write(strValue, stream, LITTLE_ENDIAN); // error : tries to call Write<std::string>, undefined 
Write< const std::string& >(strValue, stream, LITTLE_ENDIAN); // OK, Write<const std::string&> is properly defined 

的问题在于,它太冗长了什么一世 想做。

我的问题是:我怎样才能让编译器猜测我想使用的版本是“通过引用”的呢?

我是否必须更改我的模板函数以获取const引用?如果是这样,我可以专注于如果对原始类型使用“pass-by-copy”吗?

回答

9

你应该更喜欢重载到模板专业化,这样做解决您的问题,我认为:

inline void Write(const std::string& value, std::ostream& stream, endianness_t endian) { 
    // ... 
} 

我还建议回去和你的专长,你的int提到和东西转变为重载代替。

+0

红利问题:如果我按照该顺序定义Write(int64)和Write(int32),那么Write(int64)会在我传递32位int时使用吗? – Takhiarel

+0

@Takhiarel适用于超载的正常规则。如果传递一个32位'int',则将选择需要最少转换的过载(即如果存在一个,则为32位超载)。 – user3286380

0

你可以改变通用模板以const裁判经过:

template < typename T > 
void Write(const T& value, std::ostream& stream, endianness_t endian); 
+0

这可能是一个解决方案,但是这样做对原始类型没有性能损失? – Takhiarel

+0

@Takhiarel:这是一个很好的问题。我假设'Write'函数很小且很简单,它将被自动内联。然后编译器会使间接消失。 –

3

不要为要利用一切可能的类型提供重载。这首先打破了使用通用代码的逻辑。有人说,需要为每种类型提供专业化可能指出,这不是模板的最成功应用,更不用说功能模板专业化的混乱不是最漂亮的选择as Sutter says

由于您需要在这里互相排斥的类型(内置插件和非内置插件)之间的逻辑分离的一种替代方案:

template<class T> 
typename std::enable_if< std::is_fundamental<T>::value >::type foo_func(T arg) 
{ 
    std::cout << "Call for built in types" << std::endl; 
} 
template<class T> 
typename std::enable_if< !std::is_fundamental<T>::value >::type foo_func(T const &arg) 
{ 
    std::cout << "Call for non built in types" << std::endl; 
} 

解释这里的代码会发生什么:

1)的std :: is_fundamental将返回false或真编译时间取决于T是否是用户定义的ed或内置类型。

2)的std :: enable_if将“允许”函数模板的声明在第一种情况下真正在第二,所以没有解析问题可能发生。

3)因此,当为内置类型调用foo_func时,将使用第一个版本,并通过值传递T(int,float等等)(对于内置插件,这会更快),以及...您可以成像在另一种情况下发生了什么。