2013-04-27 83 views
2

如果我有一个函数模板可以为所有类型Stream(例如,何时将模板参数类型约束为具体的类

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; 
} 

还是应该函数/类模板作为一个经验法则总是尽可能通用的,即使你有特定类型的想法?

+0

如果你的模板函数只能在文档中的某些约束条件下工作。有人可能会提供一个类似istream的类,它可以在你的原始情况下工作,但不能在你的更明确的情况下工作。 – Zeta 2013-04-27 11:44:33

回答

2

我们没有任何约束或概念但在当前的C++,所以你的旧模板界面比需要更多的一般,因为它也接受未在其接口类型的流。当你调用你的函数模板并且它被重载时,这会造成容易模糊。

因此,尽可能使函数模板尽可能通用,但不是比需要的更一般。在这种情况下,你的努力是最好的。

+0

谢谢。如果我想创建一个既适用于左值又适用于右值的函数,除了将第一个签名改为“Stream &&”之外,还有其他选择吗?这对于泛型是否是有效的情况? – user657267 2013-04-27 12:06:30

+1

@ user657267你可以编写一个'is_stream'特性类,然后采用'Stream &&'并使用SFINAE来强制执行'is_stream :: type> :: value'。 – Yakk 2013-04-27 12:31:57

+0

+1提到歧义。它可以通过'enable_if'使用SFINAE来避免,但是这不是很容易编写(不提及阅读,调试,维护和检查;它只是没有乐趣)。概念将帮助我们在将来的C++版本中,在那里你可以限制模板类型。 – leemes 2013-04-30 08:28:07

1

超过限制型模板的好处是,你的函数工作,如果给定类型支持您的功能需要做的参数,没有更多的东西。这也被称为“鸭子打字”。

这对于算术计算是非常好的,它然后自动适用于所有类型的算术运算符。

。另一方面,一个很好的例子,你不希望这是(即严格类型的优势),当你想到它不能在“鸭打字”表达的类型的特定行为,例如,如果你需要的功能来a += b是相同的a = a + b(虽然这应该一贯主张,如果你重载运算符),或一个特定的(并希望)呼吁类型的函数时的副作用发生。但是,例如(“T::size()预计会返回......的数量”),此类“要求”可以(并且通常)在您的功能的文档(注释)中表达。

一般的经验法则是:如果你事先知道你要调用该函数,例如,如果你已经有了一个抽象的超类类型使用特定类型。如果您希望该类型的集合更“无限”,请使用模板。

相关问题