![](/img/trans.png)
[英]Get a reverse iterator from a forward iterator without knowing the value type
[英]How to get the value type from an output iterator?
假設我有一個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)。
正確觀察,輸出迭代器的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;
...
您可以使用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));
}
}
有不同的方法可以解決這個問題,我是這樣做的:
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;
我有另一個通常的迭代器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.