我通过以示例方式阅读Accelerated C ++实际编程来开始学习C ++,并被困在函数模板上。我了解他们的工作...以及为何有时可能有用。但是我也发现它们对调用者而言有些不雅甚至令人困惑,让我解释一下。
本书首先定义了一个功能:
vector<string> split(string& s)
映射"hello world"
到带有条目hello
和的向量word
。
然后,作者声称我们可以使我们的函数更灵活,并让调用者选择其他容器(list
例如,用a代替向量),为此,他们提出以下建议:
template <class Out> void split(const string& str, Out os)
我的问题是
我怎么知道...作为呼叫者,Out必须是一个iterator
?它实际上可以是任何东西。
如果我以某种方式弄清楚它需要一个迭代器,我仍然不知道哪种迭代器。input
output
forward
sequential
等等。
为了弄清楚这些东西,我需要看看到函数,看在迭代器使用什么运营商(++
,>
,=
)。作为该功能的“用户”,我应该关心what
它……不是how
。
函数模板似乎鼓励较弱的键入形式。在撰写本文时,我意识到这个问题可能与C ++无关,而与我使用较弱的类型化语言的经验不足有关,但我会让你来做一个判断。
我怎么知道...作为呼叫者,Out必须是迭代器?从技术上讲可以是任何东西!
这就是文档或代码作者的问题。好的模板函数可以验证所提供的类型是否符合预期。例如,可以通过几个static_assert
s来完成,以确保Out
满足期望。标准库<type_traits>
提供了许多测试,可以对类型进行测试以检查它们。
或者,您可以更详细地命名template参数:
template <class OutputIterator> void split(const string& str, OutputIterator os)
现在,没有人应该有任何疑问。
模板函数似乎鼓励动态键入。
C ++中没有动态类型。所有模板参数都在编译时解析。编译器Out
在每次编译时都非常清楚什么类型split
。
如果我以某种方式弄清楚它需要一个迭代器,我仍然不知道哪种类型。
同样,这是作者/文档的问题。如果编写了这样的函数,最好确保模板类型是您期望的static_assert
,但是测试操作符重载的存在可能很困难。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句