具有可变数量的args

时间:2016-05-01 20:14:54

标签: c++ function templates matrix variadic

我有一个Matrix模板类,我需要一个函数来设置具有可变数量的args的元素。

我应该可以这样称呼它:

aghMatrix<string> matrix;
matrix.setItems(2, 3, "torzmiae", "jestdnaci", "tablickore", "wyrazobed", "oelmntai", "rozmiaecy");

第一个整数是行数,第二个是列,其余(R * C)参数是我应该放入矩阵的元素。

它应该适用于任何数据类型,而不仅仅是原始类型。

目前,我的功能如下:

template<typename T>
template<typename... ARGS>
void aghMatrix<T>::setItems(const int rows, const int cols, ARGS... args) {
    array<T, sizeof...(args)>unpacked_args {args...};

    int row = 0;
    int col = 0;
    for (T arg : unpacked_args)
    {
        this->matrixPtr[row][col] = arg;
        col++;
        if (col == this->cols) {
            row++;
            col = 0;
        }
    }

    return;
}

我假设我的矩阵对象能够容纳所有元素。它确实编译了许多关于将所有内容都转换为unsigned int的警告,但程序无论如何都不起作用(它在启动时冻结)。

班级声明:

template<typename T>
class aghMatrix {
public:
    [...]

    template<typename... ARGS> void setItems(const int rows, const int cols, ARGS... args);

    [...]

private:
    T **matrixPtr;
    int rows;
    int cols;

    void createMatrix(const int row, const int col);

    bool checkRowCol(const int row, const int col) const;
};

Github project

1 个答案:

答案 0 :(得分:1)

编辑: 哎呀!我只是注意到你说过#34;非递归,&#34;所以我认为以下模式并不适合你。我现在仍然把它挂在这里,但我在下面提供了一个非递归解决方案(基于def make_all_pairs(list_): pivot = list_.pop(0) for el in list_: pair = (pivot, el) yield pair if len(list_) > 1: for pair in make_all_pairs(list_): yield pair x = make_all_pairs(["a","b","c","d","e"]) for el in x: print el ,因此仅适用于POD类型)

如果我理解你想做什么,那么你可能想要递归的variadic参数解包模式;这样的事情似乎可以解决问题...

va_list

通常,您希望尽可能避免直接操作内存。除非你绝对需要它(也与直接记忆操作联系在一起),也要尽可能地避免任何施法巫术。

无论如何,使用#include <iostream> using namespace std; // Helper for build_matrix, taking zero variadic arguments. // This serves as the termination in the recursive unpacking of the args. template<typename T> void build_matrix_helper(T**, size_t, size_t, size_t, size_t) { return; } // Helper for build_matrix, taking at least one variadic argument. template <typename T, typename ...ARGS> void build_matrix_helper(T** matrix, size_t curr_row, size_t curr_col, size_t row, size_t col, const T& first, ARGS...rest) { if (curr_col < col) { matrix[curr_row][curr_col] = first; ++curr_col; return build_matrix_helper<T>(matrix, curr_row, curr_col, row, col, rest...); } else { ++curr_row; curr_col = 0; return build_matrix_helper<T>(matrix, curr_row, curr_col, row, col, first, rest...); } return; } // Bare bones implementation. template<typename T, typename ...ARGS> T **build_matrix(size_t row, size_t col, ARGS...elements) { T **new_mat = new T*[row]; for (size_t j = 0; j < row; ++j) new_mat[j] = new T[col]; build_matrix_helper<T>(new_mat, 0, 0, row, col, elements...); return new_mat; } int main() { int **nm = build_matrix<int>(2, 3, 1, 2, 3, 4, 5, 6); for (size_t i = 0; i < 2; ++i) { cout << "[" << i + 1 << "]: "; for (size_t j = 0; j < 3; ++j) cout << nm[i][j] << " "; cout << endl; } delete[] nm; return 0; } 可以使用下面的非递归解决方案。

注意 由于这使用了std::va_list,因此它不适用于非POD类型。

va_list

编辑 初始化列表

正如您对OP的评论中所建议的那样,最好使用初始化列表。我知道这不是你原来要求的,但也许值得考虑:

#include <iostream>
#include <cstdarg>

using namespace std;

template <typename T>
T **build_matrix(size_t row, size_t col, ...) {
  va_list args;
  T **matrix = new T*[row];

  va_start(args, col);

  for (size_t i = 0; i < row; ++i) {
    matrix[i] = new T[col];

    for (size_t j = 0; j < col; ++j)
      matrix[i][j] = va_arg(args, T);
  }

  va_end(args);

  return matrix;
}

int main() {
  int **nm = build_matrix<int>(2, 3, 1, 2, 3, 4, 5, 6);

  for (size_t i = 0; i < 2; ++i) {
    cout << "[" << i + 1 << "]: ";
    for (size_t j = 0; j < 3; ++j)
      cout << nm[i][j] << " ";
    cout << endl;
  }

  delete[] nm;
  return 0;
}