C++ 何时将模板参数类型约束到具体类
如果我有一个可以为所有类型C++ 何时将模板参数类型约束到具体类,c++,templates,C++,Templates,如果我有一个可以为所有类型流定义的函数模板,例如 template<typename Stream> Stream& foo(Stream& stream) { return stream; } 模板 流与流(流与流) { 回流; } 将类型限制为具体类别是否有任何好处,例如 template<typename CharT, Traits> std::basic_istream<CharT, Traits>& foo(std
流定义的函数模板,例如
template<typename Stream>
Stream& foo(Stream& stream)
{
return stream;
}
模板
流与流(流与流)
{
回流;
}
将类型限制为具体类别是否有任何好处,例如
template<typename CharT, Traits>
std::basic_istream<CharT, Traits>& foo(std::basic_istream<CharT, Traits>& stream)
{
return stream;
}
模板
std::basic\u istream&foo(std::basic\u istream&stream)
{
回流;
}
或者,作为经验法则,函数/类模板是否应该尽可能通用,即使您考虑了特定的类型?模板相对于限制类型的优势在于,如果给定类型支持您的函数需要对参数执行的操作,那么您的函数就可以工作,不再需要了。这也被称为“鸭子打字”
这是非常好的,特别是对于算术计算,然后自动工作的所有类型实现算术运算符
另一方面,当您期望类型的特定行为不能用“duck-typing”表示时,例如如果您的函数要求a+=b
与a=a+b
相同,您不希望出现这种情况的一个很好的示例(即严格类型的优点)(尽管在重载运算符时,这应该始终保持不变),或者在对类型调用函数时会发生特定的(并且想要的)副作用。但是,这样的“要求”可以(并且通常)在函数的文档(注释)中表达,例如(“T::size()
预计将返回…”的数目)
一般的经验法则是:如果您事先知道要调用该函数的类型(例如,如果您已经有一个抽象超类),请使用特定类型。如果您希望类型集更“无限制”,请使用模板在当前C++中,我们没有约束或概念,因此您以前的模板接口比一般需要的更通用,因为它也接受接口中不是流的类型。这会在调用函数模板并过载时容易产生歧义。
因此,尽可能使您的函数模板通用,但不要比需要的更通用。在这种情况下,您最好将精力放在其他方面。如果您的模板函数仅在某些约束下工作,请将其放在文档中。您可以提供一个类似于istream
的类,该类可以在您的原始情况下工作,但不适用于谢谢。如果我想创建一个对左值和右值都有效的函数,除了将第一个函数的签名更改为Stream&&
?这对泛型类型有效吗?@user657267您可以编写一个is_Stream
traits类,然后使用Stream&
>使用SFINAE强制执行is_stream::value
+1以避免出现歧义。如果使用SFINAE和enable_,则可以避免,但这远不容易编写(不包括阅读、调试、维护和审阅;使用SFINAE并不有趣)概念将帮助我们在未来的C++版本中,其中可以限制模板类型。