让我们说我有一个C容器(例如,MyContainer
),其中包含的对象存储为void*
指针。迭代此容器元素的唯一方法是通过两个接口函数:
getFirstElem(MyContainer const&, void*)
:输出容器的第一个元素。getNextElem(MyContainer const&, void*)
:输出容器的下一个元素。我想编写一个泛型函数,它通过上面提到的接口函数遍历这个C容器的元素,并将它们的值复制到C ++容器中(例如std::vector
)。
到目前为止我做了什么:
template<typename OutputIterator>
void
copy_container(MyContainer const &cont, OutputIterator first) {
typename std::iterator_traits<OutputIterator>::value_type elem;
if(getFirstElem(cont, &elem)) {
do {
*first = elem;
++first;
} while(getNextElem(cont, &elem))
}
}
以上示例适用于普通迭代器。但是,它无法使用输出迭代器进行编译(例如,copy_container(cont, std::back_inserter(myvector));
)。
原因是std::iterator_traits::value_type
在参数类型是输出迭代器的情况下导致void
。
有没有办法让这个泛型函数也适用于输出迭代器?
我知道在C ++ 11中可以使用decltype
(例如decltype(*first)
)来完成,但我对C ++ 11之前的解决方案特别感兴趣,因为我使用旧的C ++编译器(gcc v4.4.7)。
答案 0 :(得分:7)
正确观察,输出迭代器的value_type
为void
。所以除了替换它之外别无选择:
typename std::iterator_traits<OutputIterator>::value_type elem;
用这个
decltype(*first) elem;
(即使标准不能保证它能够正常工作 - 也可以通过解除引用输出迭代器来返回代理)。
正如您所说,没有C ++ 11解决方案,因此可能需要进行重新设计。以下是一些选项:
您可以将引用传递给容器,而不是第一个元素的迭代器。看起来你想要的只是一个push_back
。
template<template<typename,typename> class stlContainer>
void copy_container(
MyMontainer const &cont, OutputIterator first)
{
// insertion in stlContainer
然后您需要的是一层特征,以便分配到每个容器的正确插入实现
值类型可以是额外的模板参数。
template<typename value_type, typename OutputIterator>
void copy_container(MyMontainer const &cont, OutputIterator first)
{
value_type elem;
...
答案 1 :(得分:3)
您可以使用typetraits和specialization
template <typename IT>
struct it_value_type
{
typedef typename std::iterator_traits<IT>::value_type elem;
};
template <typename Container>
struct it_value_type<std::back_insert_iterator<Container>>
{
typedef typename Container::value_type elem;
};
template <typename Container>
struct it_value_type<std::front_insert_iterator<Container>>
{
typedef typename Container::value_type elem;
};
然后您的代码变为:
template<typename OutputIterator>
void
copy_container(MyContainer const &cont, OutputIterator first) {
typename it_value_type<OutputIterator>::elem elem;
if (getFirstElem(cont, &elem)) {
do {
*first = elem;
++first;
} while (getNextElem(cont, &elem));
}
}
答案 2 :(得分:0)
有不同的解决方法,我这样做:
template <class T>
std::enable_if_t<!std::is_same_v<typename T::container_type::value_type, void>, size_t> read(T first, size_t count)
{
typedef typename T::container_type::value_type value_type;
我有另一个用于通常的迭代器。