你可以这样做:
template <typename T, unsigned int N>
std::ostream & operator<<(std::ostream & os, const T (&arr)[N])
{
// ..
return os;
}
这仅适用于编译时的阵列,当然。请注意,当T
是内置类型或std
名称空间中的类型时,不允许您实例化此模板!
如果可能,可能最好使它内联,因为每个N
都会导致单独实例化。 (该pretty printer有这样的一个例子。)
你会发现,虽然,毯子模板带来了模棱两可的,因为os << "Hello"
现在有两个可能的过载:模板匹配const char (&)[6]
,和(非模板)过载衰减到指针const char *
,它们都具有相同的转换序列。我们可以通过禁用我们的字符数组超载解决此问题:
#include <ostream>
#include <type_traits>
template <typename T, unsigned int N>
typename std::enable_if<!std::is_same<T, char>::value, std::ostream &>::type
operator<<(std::ostream & os, const T (&arr)[N])
{
// ..
return os;
}
事实上,会更加普遍,你还可以使basic_ostream
参数模板参数:
template <typename T, unsigned int N, typename CTy, typename CTr>
typename std::enable_if<!std::is_same<T, char>::value,
std::basic_ostream<CTy, CTr> &>::type
operator<<(std::basic_ostream<CTy, CTr> & os, const T (&arr)[N])
{
// ..
return os;
}
鉴于事实T
必须是用户定义的类型,您甚至可以用is_fundamental<T>
替换is_same<T, char>
以获得更多检查(但用户仍然不能将其用于标准库类型的数组)。
谢谢,不过我还是要说不明白为什么它会导致每个N单独实例化,如果没有实现内联? – Alcott
嗯,它是一个模板,所以每个模板实例最终都可以作为二进制文件中的一个独立函数。如果你内联,你可以完全避免函数调用,尽管这最终取决于编译器。 –
明白了。用这个运算符<<有2个模板参数,我怎样才能指定第二个参数N?显然,我不能仅仅使用“cout << ar;”,我可以吗? – Alcott