2

我想编写自己的代码来迭代一个 n 维向量(其中维度是已知的)。这是代码:

void printing(const auto& i, const int dimension){
    int k= dimension;
    for(const auto& j: i){
        if(k>1){
            cout<<"k: "<<k<<endl;
            printing(j, --k);
        }
        else{
            //start printing
            cout<<setw(3);
            cout<<j; //not quite sure about this line
        }
        cout<<'\n';
    }
}

我收到一个错误:

main.cpp:21:5: error: ‘begin’ was not declared in this scope
 for(const auto& j: i){
 ^~~

有人可以帮我纠正它或给我一个更好的方法来打印矢量吗?在此先感谢您的时间。

4

1 回答 1

2

如果维度在编译时已知,则可以使用template将维度作为非类型参数的 a 轻松解决。

template <std::size_t Dimensions>
void printing(const auto& i){
    if constexpr (Dimensions != 0) {
        for(const auto& j: i){
            // I'm not sure if it is intentional to print 'k' each iteration, 
            // but this is kept for consistency with the question
            cout<<"k: " << Dimensions << endl;
            printing<Dimensions - 1u>(j);
        }
    } else {
        cout << setw(3);
        cout << j;
        cout << '\n';
    }
}

对于二维向量,用途是:

printing<2>(vec);

Live Example


但是,如果您总是知道这const auto& i将是一种std::vector类型,那么您可以通过根本不使用auto参数来更轻松地解决这个问题,而是使用template匹配:

// called only for the vector values
template <typename T>
void printing(const std::vector<T>& i){
    for(const auto& j: i){
        // possibly compute 'k' to print -- see below
        printing(j);
    }
}

// Only called for non-vector values
template <typename T>
void printing(const T& v) {
    cout << setw(3);
    cout << v;
    cout << '\n';
}

Live Example

要计算向量的“维度”,您可以为此编写递归类型特征:

#include <type_traits> // std::integral_constant

// Base case: return the count
template <std::size_t Count, typename T>
struct vector_dimension_impl
  : std::integral_constant<std::size_t, Count> {};
 
// Recursive case: add 1 to the count, and check inner type
template <std::size_t Count, typename T, typename Allocator>
struct vector_dimension_impl<Count, std::vector<T,Allocator>> 
  : vector_dimension_impl<Count + 1u, T> {};

// Dispatcher
template <typename T>
struct vector_dimension : vector_dimension_impl<0u, T> {};

// Convenience access
template <typename T>
inline constexpr auto vector_dimension_v = vector_dimension<T>::value;
 
// Simple tests:
static_assert(vector_dimension_v<std::vector<int>> == 1u);
static_assert(vector_dimension_v<std::vector<std::vector<int>>> == 2u);
static_assert(vector_dimension_v<std::vector<std::vector<std::vector<int>>>> == 3u);

Live Example

使用上述递归特征,您可以获得每个templated 向量类型的“维度”,而根本不需要用户传入值。

如果您仍然想k: 每次都打印,您可以简单地使用上面的内容:

cout << "k: " << vector_dimension_v<T> << endl;

这仅在类型已知为 a 时才有效vector——但它可以使用概念编写,以处理遵循 a 之类的抽象定义的任何内容vector

如果您希望它适用于任何类似范围的类型,那么您可以将vector-overload 替换为 a requires(std::ranges::range<T>),并将用于查找维度的模板专业化更改为也使用相同的维度。我不会用所有这些代码污染答案,因为它与上面大致相同 - 但我将在下面链接到它:

Live Example

于 2021-07-11T18:24:23.313 回答