模板功能:混合逐个复制传递和按引用传递

Template functions : mixing pass-by-copy & pass-by-reference

本文关键字:复制 按引用传递 功能 混合      更新时间:2023-10-16

我有一个模板函数,负责将模板值写入流。它看起来像这样:

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

我已经实现了基本类型的版本:int、uint、float等。现在,如果我想写一个更复杂的结构,比如一个std::字符串,我这样声明:

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

问题是,对于我想做的事情来说,它太冗长了

我的问题是:我如何让编译器猜测我想要使用的版本是"通过引用"的版本?

我是否必须更改模板函数以获取常量引用?如果是的话,我可以专门化是否对基元类型使用"传递副本"吗?

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

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

我还建议您回过头来,将您提到的int等所有专业化改为重载。

不要为您想要使用的每种可能的类型提供重载。这首先打破了使用泛型代码的逻辑。话虽如此,为每种类型提供专业化的需求可能会指出,这并不是模板最成功的应用,更不用说像Sutter所说的那样,扰乱功能模板专业化并不是最漂亮的选择

由于您需要在互斥类型(内置和非内置)之间进行逻辑分离,因此有一个替代方案:

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_fundmental在编译时将分别返回false或true,具体取决于T是用户定义类型还是内置类型。

2) std::enable_if将"允许"在第一种情况下为true声明函数模板,在第二种情况下声明false,因此不会出现解决问题。

3) 因此,当为内置类型调用foo_func时,将使用第一个版本,并按值传递T(int、float等)(这对内置类型来说更快)。。。你可以想象在另一种情况下会发生什么。

您可以更改通用模板以传递const-ref:

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