我有:
void add_all_msgs(std::deque<Message>::iterator &iter);
如何使该功能“通用”,因此可以采用任何类型的输入器?只要迭代器迭代Message,我就不在乎它是否正在迭代一个deque,一个向量或其他东西。 - 这在C ++中是否可以直接进行?
答案 0 :(得分:13)
template <typename Iterator>
void add_all_messages(Iterator first, Iterator last)
用法:
vector<message> v;
add_all_messages(v.begin(), v.end());
您需要指定结束,否则您将不知道何时停止!它还为您提供了仅添加容器子范围的灵活性。
答案 1 :(得分:6)
template<class InputIterator>
void add_all_msgs(InputIterator iter);
用法:
std::deque<Message> deq;
add_all_msgs(deq.begin());
答案 2 :(得分:5)
如果希望编译器检查迭代器是否实际引用Message
个对象,可以使用如下所示的技术。
template <typename InputIterator, typename ValueType>
struct AddAllMessages { };
template <typename InputIterator>
struct AddAllMessages<InputIterator, Message> {
static void execute(const InputIterator &it) {
// ...
}
};
template <typename InputIterator>
void add_all_msgs(const InputIterator &it) {
AddAllMessages<InputIterator,
typename std::iterator_traits<InputIterator>::value_type>::execute(it);
}
答案 3 :(得分:2)
如果您不想模板化add_all_msgs函数,可以使用adobe::any_iterator:
typedef adobe::any_iterator<Message, std::input_iterator_tag> any_message_iterator;
void add_all_msgs(any_message_iterator begin, any_message_iterator end);
答案 4 :(得分:1)
上述内容稍微简单一点(因为它利用了现有的库):
#include <boost/static_assert.hpp> // or use C++0x static_assert
#include <boost/type_traits/is_same.hpp>
template <typename InputIterator>
void add_all_msgs( InputIterator it ) {
BOOST_STATIC_ASSERT(( boost::is_same<
typename std::iterator_traits<InputIterator>::value_type,
Message>::value ));
// ...
答案 5 :(得分:1)
使用C ++风格的迭代器很难实现动态多态性。 operator++(int)
按值返回,afaik是难以处理的:你不能有一个虚拟成员函数,它按值返回*this
而不会被切片。
如果可能的话,我建议像其他人一样使用模板。
但是如果你确实需要动态多态,例如因为你不能像模板那样公开add_all_msgs的实现,那么我认为你可以伪装成Java,就像这样:
struct MessageIterator {
virtual Message &get() = 0;
virtual void next() = 0;
// add more functions if you need more than a Forward Iterator.
virtual ~MessageIterator() { }; // Not currently needed, but best be safe
};
// implementation elsewhere. Uses get() and next() instead of * and ++
void add_all_msgs(MessageIterator &it);
template <typename T>
struct Adaptor : public MessageIterator {
typename T::iterator wrapped;
Adaptor(typename T::iterator w) : wrapped(w) { }
virtual Message &get() {
return *wrapped;
}
virtual void next() {
++wrapped;
}
};
int main() {
std::deque<Message> v;
Adaptor<std::deque<Message> > a(v.begin());
add_all_msgs(a);
}
我已经检查过这个编译,但我还没有测试过,我以前从未使用过这个设计。我也没有对常识感到困扰 - 在实践中你可能想要一个const Message &get() const
。目前,适配器无法知道何时停止,但是你开始使用的代码也没有,所以我也忽略了它。基本上你需要一个hasNext
函数,它将wrapped
与提供给构造函数的结束迭代器进行比较。
您可以使用模板函数和const引用执行某些操作,以便客户端不必了解或声明该讨厌的适配器类型。
[编辑:想想看,最好有一个存根add_all_msgs
函数模板,它将其参数包装在一个Adapter中,然后调用real_add_all_msgs
。这完全隐藏了客户端的适配器。]
答案 6 :(得分:0)
#include <deque>
#include <vector>
#include <list>
#include <string>
using namespace std;
template<typename T>
void add_all_msgs(T &iter)
{
}
int _tmain(int argc, _TCHAR* argv[])
{
std::deque<string>::iterator it1;
std::vector<string>::iterator it2;
std::list<string>::iterator it3;
add_all_msgs(it1);
add_all_msgs(it2);
add_all_msgs(it3);
return 0;
}