这个程序不完全符合前相关问题,但基本上是一样的:给定一个元素集合和一个索引集合,根据索引序列通过迭代器集合元素返回。下面是:
#include <exception>
#include <iostream>
#include <iterator>
#include <list>
#include <sstream>
#include <vector>
template<typename ForwardIterator, typename IndexIterator>
class indirection_iterator {
public:
indirection_iterator(ForwardIterator element_begin,
ForwardIterator element_end,
IndexIterator index_begin,
IndexIterator index_end)
:
m_element_begin{element_begin},
m_element_end{element_end},
m_index_begin{index_begin},
m_index_end{index_end},
m_index_current{index_begin},
m_elements{std::distance(element_begin, element_end)}
{}
indirection_iterator begin()
{
return indirection_iterator{m_element_begin,
m_element_end,
m_index_begin,
m_index_end,
m_index_begin};
}
indirection_iterator end()
{
return indirection_iterator{m_element_begin,
m_element_end,
m_index_begin,
m_index_end,
m_index_end};
}
auto operator*()
{
auto index = *m_index_current;
check_index(index, m_elements);
auto element_iterator = m_element_begin;
std::advance(element_iterator, index);
return *element_iterator;
}
void operator++()
{
std::advance(m_index_current, 1);
}
bool operator!=(indirection_iterator const& other)
{
return m_index_current != other.m_index_current;
}
private:
indirection_iterator(ForwardIterator element_begin,
ForwardIterator element_end,
IndexIterator index_begin,
IndexIterator index_end,
IndexIterator index_current)
:
m_element_begin{element_begin},
m_element_end{element_end},
m_index_begin{index_begin},
m_index_end{index_end},
m_index_current{index_current},
m_elements{std::distance(element_begin, element_end)}
{}
template<typename IndexIter>
using index_type = typename std::iterator_traits<IndexIter>::value_type;
ForwardIterator m_element_begin;
ForwardIterator m_element_end;
IndexIterator m_index_begin;
IndexIterator m_index_end;
IndexIterator m_index_current;
typename std::iterator_traits<ForwardIterator>::difference_type m_elements;
template<typename index_type>
void check_index(index_type index, size_t elements)
{
if (index < 0)
{
std::stringstream ss;
ss << "index(" << index << ") < 0";
throw std::runtime_error{ss.str()};
}
if (index >= elements)
{
std::stringstream ss;
ss << "index(" << index << ") >= elements(" << elements << ")";
throw std::runtime_error{ss.str()};
}
}
};
static std::vector<char> get_alphabet() {
std::vector<char> alphabet;
for (char ch = 'a'; ch <= 'z'; ch++)
{
alphabet.push_back(ch);
}
for (char ch = 'A'; ch <= 'Z'; ch++)
{
alphabet.push_back(ch);
}
alphabet.push_back(',');
alphabet.push_back(' ');
alphabet.push_back('!');
alphabet.push_back('\n');
return alphabet;
}
int main(int argc, const char * argv[]) {
std::vector<char> alphabet = get_alphabet();
std::list<int> char_indices =
{ 33, 4, 11, 11, 14, 52, 53, 48, 14, 17, 11, 3, 54, 55 };
indirection_iterator<decltype(alphabet.cbegin()),
decltype(char_indices.cbegin())> indirection_iter {
alphabet.cbegin(),
alphabet.cend(),
char_indices.cbegin(),
char_indices.cend()
};
std::copy(indirection_iter.begin(),
indirection_iter.end(),
std::ostream_iterator<char>{std::cout});
return 0;
}我想听听如何使它更有用,以及如何使它更地道的C++。
发布于 2018-01-18 12:40:26
我知道这只是测试代码,而不是审查的真正主题,但值得一提的是。
for (char ch = 'a'; ch <= 'z'; ch++)
{
alphabet.push_back(ch);
}这并不一定要做您认为它做的事情;它取决于目标的字符编码。在EBCDIC语言环境中,这将插入41个值,这将抛出您的索引。
从字符串文本初始化更安全、更清晰:
static std::vector<char> get_alphabet() {
static char const s[] = ""
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
", !\n";
return {std::begin(s), std::end(s)};
}GCC警告( -Weffc++),operator++()应该按惯例返回对*this的引用,而不是void。许多方法也可以/应该声明为const (至少根据我的测试,begin、end、operator*、operator!=和check_index )。
用户不可计算建议我将操作者超载 (关于cppreference.com)作为常用函数签名的有用列表。
https://codereview.stackexchange.com/questions/185343
复制相似问题