我有一个模板函数,负责将模板值写入流。它看起来像这样:
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
...
}
如果没有明确调用“pass-by-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”?
答案 0 :(得分:9)
您应该更喜欢重载模板专业化,这样做可以解决您的问题:
inline void Write( const std::string& value, std::ostream& stream, endianness_t endian ) {
// ...
}
我还建议您返回并更改您为int
提及的所有专业知识,并将内容更改为重载。
答案 1 :(得分: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或true,具体取决于T是用户定义还是内置类型。
2)std :: enable_if将在第一种情况下“允许”声明 true 的功能模板,在第二种情况下使用 false ,因此没有解决问题的能力发生。
3)因此,当为内置类型调用foo_func时,将使用第一个版本,并且通过值传递T(int,float等)(对于内置函数更快)并且......你可以成像在另一种情况下会发生什么。
答案 2 :(得分:0)
您可以将通用模板更改为const ref:
template < typename T >
void Write( const T& value, std::ostream& stream, endianness_t endian );