簡體   English   中英

如何從輸出迭代器中獲取值類型?

[英]How to get the value type from an output iterator?

假設我有一個C容器(例如, MyContainer ),其中包含的對象存儲為void*指針。 迭代此容器元素的唯一方法是通過兩個接口函數:

  1. getFirstElem(MyContainer const&, void*) :輸出容器的第一個元素。
  2. 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_typevoid 除了替換這個之外沒什么可做的:

typename std::iterator_traits<OutputIterator>::value_type elem;

有了這個

decltype(*first) elem;

(即使標准不保證它可以工作 - 可以通過取消引用輸出迭代器來返回代理)。

正如您所說,沒有C ++ 11解決方案,因此可能需要進行重新設計。 以下是一些選項:

1.通過容器

您可以將引用傳遞給容器,而不是第一個元素的迭代器。 看起來你想要的只是一個push_back

template<template<typename,typename> class stlContainer>
void copy_container(
    MyMontainer const &cont, OutputIterator first) 
{ 
    // insertion in stlContainer

那么你所需要的只是一層特征,可以調度到每個容器的正確插入實現

2.傳遞額外的模板參數

值類型可以是額外的模板參數。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM