C++ 模板专门化帮助
我正在使用/学习模板函数专门化规则。我从这个函数开始C++ 模板专门化帮助,c++,templates,C++,Templates,我正在使用/学习模板函数专门化规则。我从这个函数开始 template<typename T> std::string toString(const T& t) { ostringstream out; out << t; return out.str(); } 模板 标准::字符串到字符串(常量T&T) { ostringstream out; 我认为这应该行得通: template <typename T> std
template<typename T>
std::string toString(const T& t)
{
ostringstream out;
out << t;
return out.str();
}
模板
标准::字符串到字符串(常量T&T)
{
ostringstream out;
我认为这应该行得通:
template <typename T>
std::string to_string(const T &)
{
...
}
// non templated
std::string to_string(const char* x)
{
...
}
模板
std::字符串到_字符串(常量T&)
{
...
}
//非模板
std::字符串到_字符串(常量字符*x)
{
...
}
为什么要专门化?只需重载函数。通常不需要完全专门化函数模板
template <typename T>
std::string toString(const T& in)
{
ostringstream out;
out << in;
return out.str();
}
std::string toString(char const* in)
{
return in;
}
您可以省略专业化S2
,然后“There”
和”,Bob“
将使用S3
请注意,实际上,这根本不是专门化。我通过创建新的函数模板进行了欺骗。但我必须将size\u t
参数输入;如果您为N
选择一个值并将其作为具体类型的一部分写入函数签名中,您只能在这里进行真正的专门化,或者,如果您可以部分专门化函数模板。它不起作用的原因是它实际上不是正确的类型。字符串文字不是const char*
类型,它们是const char[N]
类型。当您传递字符串文字时,t被推断为char[N]。这是一个精确匹配,而不是专门化。不能为字符串文字设置特殊化,因为这需要一个部分规范,C++不支持部分函数特化。 < P>我和SunStudio C++编译器有类似的问题。
首先,我使用了两个数组重载(char(&)[N]
带和不带const
)和两个指针重载(char*
和const char*
)
令我惊讶的是,像toString(“quoted literal”)
这样的调用使用了const char*
,而且似乎不可能强制编译器选择数组重载。更有趣的是,对于char lit[]=“literal”
这样的参数,toString(lit)
选择了数组重载
经过一番思考,我找到了一种方法,使代码表现为部分函数专门化
首先,定义一个模板来区分(const)char*
和(const)char[N]
template<typename T>
struct is_literal {
};
template<size_t N>
struct is_literal<const char[N]> {
typedef std::string type;
static const size_t len = N - 1; // subtract terminating null char from N
};
template<size_t N>
struct is_literal<char[N]> {
typedef std::string type;
static const size_t len = N - 1;
};
template<>
struct is_literal<const char*> {
typedef std::string ptr_type;
};
template<>
struct is_literal<char*> {
typedef std::string ptr_type;
};
某些编译器可能在const
方面存在问题-对于那些const T&arg
可能需要重载
当我经常调用函数并希望保存strlen
调用或用simplememcpy
替换strcpy
调用时,我使用此解决方案主要是出于性能原因。是的,它会起作用,但我想研究模板专门化。我知道,这是一种人为的情况。因此我想您可能需要专门化一次是conchchar *,一次是char *。因为char不是const char *,我猜C++不匹配专业化,使用更通用的函数。如果你想要const char *和char *使用相同的专门化,我想你必须把Car参数从Cch*到const char *。emplate专门化是指函数模板专门化很少有帮助。传递字符串文字后,它将推断为与指针类型不匹配的数组类型(这是专门化,因此类型必须完全匹配)。对于您显示的重载,它将使用第二个toString
,因为转换序列将是不明确的,但第二个是非模板的,因此获胜。@Tomalak:我理解正确了吗:您在T
之后编写const
(第一个模板函数std::string toString(T const&T)
),在T是指针的情况下,使参考常数成为常数?@Christian:没错。对于专门化,参数必须匹配;因此我为T
选择char-const*
,结果是char-const*const&
,表示有效的专门化。
template <typename T>
std::string toString(const T& in)
{
ostringstream out;
out << in;
return out.str();
}
std::string toString(char const* in)
{
return in;
}
template <typename T>
std::string toString(T const & t) {
ostringstream out;
out << t;
return out.str();
}
template <>
std::string toString(char const* const & s) {
cout << "(S1)";
return std::string(s);
}
template <size_t N>
std::string toString(char (&s)[N]) {
cout << "(S2)";
return std::string(s);
}
template <size_t N>
std::string toString(char const (&s)[N]) {
cout << "(S3)";
return std::string(s);
}
int main() {
const char* s1 = "Hi";
cout << toString(s1) << endl;
char s2[] = "There";
cout << toString(s2) << endl;
cout << toString(", Bob") << endl;
}
// Output:
// (S1)Hi
// (S2)There
// (S3), Bob
template<typename T>
struct is_literal {
};
template<size_t N>
struct is_literal<const char[N]> {
typedef std::string type;
static const size_t len = N - 1; // subtract terminating null char from N
};
template<size_t N>
struct is_literal<char[N]> {
typedef std::string type;
static const size_t len = N - 1;
};
template<>
struct is_literal<const char*> {
typedef std::string ptr_type;
};
template<>
struct is_literal<char*> {
typedef std::string ptr_type;
};
template<typename T>
typename is_literal<T>::type
toString(T& arg)
{
std::cout << "(literal)";
// note the second argument which means length
// this can be a performance gain because no strlen call is needed
return std::string(arg, is_literal<T>::len);
}
template<typename T>
typename is_literal<T>::ptr_type
toString(T& arg)
{
std::cout << "(raw pointer)";
return std::string(arg);
}