繁体   English   中英

如何将 std::pair 迭代器传递给函数模板并推导出迭代器类型?

[英]How to pass a std::pair of iterators to a function template and have the iterator types deduced?

我试图将两个迭代器包装成一个 std::pair 并将其传递给一个函数参数,但希望迭代器的类型是通用的。

这对本身在迭代器类型上进行了模板化......

template<typename Iterator>
using iteratorPair = std::pair<Iterator,Iterator>;

...然后模板函数本身具有签名...

template<typename T, typename U,template<typename> class IteratorPair, template<typename> class IteratorPairInt>
void
sortUsingIndicesToTargetContainerPair(
    const IteratorPair<T>& rangeToSortSource,
    const IteratorPair<T>& rangeToSortTarget,
    const IteratorPairInt<U>& indicesRange)
{ ...}

我正在做所有这些,以便我可以通过钎焊初始化调用该函数......

std::vector<int> vecs{0,1,2,3,4,5,6,7,8,9};
std::vector<int> indices{9,8,7,6,5,4,3,2,1,0};

auto copy = vecs;
sortUsingIndicesToTargetContainerPair({vecs.begin(), vecs.end()},
                                      {copy.begin(), copy.end()}, 
                                      {indices.begin(), indices.end()});

如果我在调用函数时使用它的名称显式构造类型,我可以让它工作,但如果可能的话,我想使用花括号初始化。

任何帮助,将不胜感激! 谢谢

我可以建议下面的解决方案。 想法:不要尝试直接推导类型,而是添加一个适配器函数,将参数数组转换为迭代器对:

template<typename T, typename TIndex, std::size_t N>
constexpr void FAdaptor
(
    const T(&rangeToSortSource)[N],
    const T(&rangeToSortTarget)[N],
    const TIndex(&indicesRange)[N]
)
{ 
  static_assert(2 == N, "must be pair");    
  
  sortUsingIndicesToTargetContainerPair
  (
    IteratorPair<T>(rangeToSortSource[0], rangeToSortSource[1]),
    IteratorPair<T>(rangeToSortTarget[0], rangeToSortTarget[1]),
    IteratorPair<TIndex>(indicesRange[0], indicesRange     [1])
  );  
}

完整示例:

#include <iostream>
#include <initializer_list>
#include <vector>
#include <utility>

template<typename Iterator>
using IteratorPair = std::pair<Iterator,Iterator>;


template<typename T, typename TIndex>
void sortUsingIndicesToTargetContainerPair
(
    const IteratorPair<T>& rangeToSortSource,
    const IteratorPair<T>& rangeToSortTarget,
    const IteratorPair<TIndex>& indicesRange)
{ 
    
}

template<typename T, typename TIndex, std::size_t N>
constexpr void sortUsingIndicesToTargetContainerPair2
(
    const T(&rangeToSortSource)[N],
    const T(&rangeToSortTarget)[N],
    const TIndex(&indicesRange)[N]
)
{ 
  static_assert(2 == N, "must be pair");    
  
  sortUsingIndicesToTargetContainerPair
  (
    IteratorPair<T>(rangeToSortSource[0], rangeToSortSource[1]),
    IteratorPair<T>(rangeToSortTarget[0], rangeToSortTarget[1]),
    IteratorPair<TIndex>(indicesRange[0], indicesRange     [1])
  );  
}


int main() {
  std::vector<int> vecs{0,1,2,3,4,5,6,7,8,9};
  std::vector<int> indices{9,8,7,6,5,4,3,2,1,0};

  auto copy = vecs;
  sortUsingIndicesToTargetContainerPair(std::make_pair(vecs.begin(), vecs.end()),
                                        std::make_pair(copy.begin(), copy.end()), 
                                        std::make_pair(indices.begin(), indices.end()));

  sortUsingIndicesToTargetContainerPair2({vecs.begin(), vecs.end()},
                                         {copy.begin(), copy.end()}, 
                                         {indices.begin(), indices.end()});
 
  std::cout << "ok\n";
  return 0;
}

如果您已经定义了iteratorPair<Iterator> ,则不需要template<typename> class IteratorPair

我还建议按值采用(成对)迭代器。 您是否通过常量引用获取(成对)指针?

template<typename T, typename U>
void sortUsingIndicesToTargetContainerPair(
    iteratorPair<T>& rangeToSortSource,
    iteratorPair<T>& rangeToSortTarget,
    iteratorPair<U>& indicesRange);

你有几个问题:

  • {..}没有类型,只能推导出为std::initializer_list<T>T(&)[N]

  • 模板参数不能将别名推断为别名,

    iteratorPair<SomeType> (又名std::pair<SomeType, SomeType> )不会匹配template <typename> class Pair

    我们在默认模板( std::vector<T, Allocator /*=SomeDefault<T>*/> for template <typename T> Container )中遇到了类似的“问题”,该问题已在 C++17 中解决。 我不认为可能有“冲突”/重复的别名的解决方案是可能的。

    正如 Caleth 所提到的,您可能无论如何都不想对此进行扣除。

  • 您的iteratorPair似乎定义了一个范围,但您的常量具有误导性。 const iteratorPair<std::vector<int>::iterator>允许修改底层容器。 使用真正的范围类型似乎更合适。

为了允许您的调用语法,您可能会摆脱std::pair并执行以下操作:

// SourceIt might be different than TargetIt (iterator and const_iterator mainly)
template <typename SourceIt, typename TargetIt, typename IndexesIt>
void sortUsingIndicesToTargetContainerPair(
    const SourceIt (&rangeToSortSource)[2],
    const TargetIt (&rangeToSortTarget)[2],
    const IndexesIt (&indicesRange)[2])
{ /*...*/ }

但是,为了保持您对范围的想法,您甚至可以这样做

template <typename Source, typename Target, class Indexes>
void
sortUsingIndicesToTargetContainerPair(
    const Source& rangeToSortSource,
    Target& rangeToSortTarget,
    /*const*/ Indexes& indicesRange)
{ /*...*/}

你甚至有更简单的调用语法:

sortUsingIndicesToTargetContainerPair(vecs, copy, indices);
sortUsingIndicesToTargetContainerPair(my_sub_range(vecs, /*..*/),
                                      my_sub_range(copy, /*..*/),
                                      my_sub_range(indices, /*..*/));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM