c++ - 以范围作为参数

标签 c++

许多 STL 算法都采用范围和参数。我有兴趣了解在我的构造函数中采用范围需要什么。

假设我正在创建一个 Matrix 类。构造函数会是什么样子? 我相信前向迭代器是最通用的。

#include <algorithm>
#include <iterator>
#include <vector>

using namespace std;

template <class T>
class Matrix
{
private:

    const size_t                m_order;
    std::vector<std::vector<T>> m_data;

public:

    Matrix(const size_t order, forward_iterator_tag begin, forward_iterator_tag end)
        :
        m_order(order)
      , m_data (order, std::vector<T>(order))
    {
        if (std::distance(begin, end) != order * order)
        {
            throw std::runtime_error("invalid params");
        }

        for (size_t currentRow = 0; currentRow < m_order; ++currentRow)
        {
            for (size_t currentColumn = 0; currentColumn < m_order; ++currentColumn)
            {
                m_data[row].push_back(*begin);

                if (++begin == end)
                {
                    throw std::runtime_error("invalid params");
                }
            }
        }
    }

    T GetElement(size_t row, size_t column) const
    {
        if (row > order || column > order)
        {
            throw std::runtime_error("invalid params");
        }

        return m_data[row][column];
    }
};


//------------------------------------------------------------------------------
// Finds all permutations of the distinct numbers that make up a matrix of order n, from 1 to n^2
std::vector<std::vector<size_t>> GetAllPermutations(size_t order)
{
    std::vector<std::vector<size_t>> result;

    // It is important than we have these sorted least to greatest to start, in order to use the next_permutation algorithm
    std::vector<size_t> elements;
    for(size_t currentNumber = 1; currentNumber <= order * order; ++currentNumber)
    {
        elements.push_back(currentNumber);
    }

    do
    {
        // Store the current permutation
        result.push_back(elements);

    } while (std::next_permutation(elements.begin(), elements.end()));

    return result;
}

int main()
{
    const size_t order = 3;
    std::vector<std::vector<size_t>> permutations = GetAllPermutations(order);

    Matrix<size_t> matrix(order, permutations.begin(), permutations.end());

    return 0;
}

但是迭代器显然不是正确的类型。我用什么?

最佳答案

您将构造函数的迭代器参数声明为 std::forward_iterator_tag 的实例,这是一个 iterator tag ,而不是实际的迭代器。

迭代器标签用于将模板专门化限制为特定类型的迭代器。

例如,假设一个算法需要随机访问迭代器。如果将非随机访问迭代器传递给它,它可能会产生编译器错误。

或者,给定算法的多个重载可以使用迭代器标签来限制它们接受的迭代器类型,因此当传递不同类型的迭代器时,它们可以使用不同的逻辑/优化。

在您的情况下,要执行您想要的操作,您需要将构造函数更改为具有迭代器类型的模板参数(就像 STL 算法一样):

template<class InputIt>
Matrix(const size_t order, InputIt first, InputIt last)

现在,您可以传入您想要的任何类型的迭代器(只要取消引用迭代器产生的值与您的 Matrix 类的 T 模板参数兼容,因为这就是您的构造函数体使用迭代器值的方式。

或者,如果你想确保只有前向输入迭代器的迭代器被传入,而不是任何其他类型的迭代器,你可以做更多这样的事情:

private:
    template<class InputIt>
    Matrix(const size_t order, InputIt first, InputIt last, std::forward_iterator_tag)
    {
        // initialization here ...
    }

public:
    template<class InputIt>
    Matrix(const size_t order, InputIt first, InputIt last)
        : Matrix(order, first, last, typename std::iterator_traits<InputIt>::iterator_category())
    {
    }

仅当 InputIt 是一个迭代器类型时,代码才会编译,其 std::iterator_traits 特化提供了一个 iterator_category ,即 std::forward_iterator_tag 或后代。

这种方法通常称为 Tag Dispatching .

关于c++ - 以范围作为参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49661373/

相关文章:

c++ - Pimpl 习语和交换

c++ - 生成范围内的一组唯一元素

c++ - VC++ 2012 中出乎意料的模棱两可的重载解析

c++ - 遍历 STL 列表

c++ - 静态初始化的对象不能放在 try block 中

c++ - 带 () 的 C 对象 - 它有什么作用?

c++ - 服务器如何存储客户端的IP地址?

c++ - std::cout 字符串崩溃

c++ - 如何避免 typedef?

c++ - 从不同类型的模板类创建对象