所以我有类似的东西:
template<unsigned int W,unsigned int H>
class Class
{
int data[W][H];
Class(const (&_data)[W][H])
{
for (int x=0;x<W;x++)
for (int y=0;y<H;y++)
data[x][y] = _data[x][y];
}
template<class... args>
Class()
{
/// black magic
}
}
我能替换“黑魔法”,所以第二个构造函数会接受W * H整数? 例如:
Class<3,2> class1(1,2,3,4,5,6);
答案 0 :(得分:2)
首先,您的示例中存在一些语法错误,因为在类声明之后缺少分号并且构造函数是私有的。
除此之外,如果您想将数字存储在row-major order中,那么您应该将矩阵/ 2d数组声明为int data[H][W]
(高度优先,然后是宽度)。
要存储可变参数包中的值,您只需在容器的内部展开它们即可。 std::array
,并使用列表初始化。
template <typename... Args>
Class(Args&&... args) {
const std::array<int, H * W> temp{std::forward<Args>(args)...};
/* ... */
};
我还使用universal references并完美转发以保留包的引用类型。
要填充二维数组,您只需迭代temp
中的所有元素并将它们存储在成员数组中。
for (std::size_t h = 0; h != H; ++h)
for (std::size_t w = 0; w != W; ++w)
data[h][w] = temp[h * W + w];
答案 1 :(得分:2)
这有效:
#include <array>
#include <utility>
#include <iostream>
template<unsigned W,unsigned H>
struct Foo
{
std::array<std::array<int, H>, W> data;
template<typename... Args>
Foo(Args&&... args):
data{ std::forward<Args>(args)... }
{}
};
int main()
{
Foo<2,2> x(1,2,3,4);
for( auto&& a : x.data ) {
for( unsigned z : a ) {
std::cout << z << ",";
}
std::cout << "\n";
}
但是会在内部array
中公开存储顺序。
std::array
是一个围绕原始C数组的语法糖。
答案 2 :(得分:2)
有一些替代答案可能更实用,更易于实现,但我将展示如何使用编译时for循环实现这一目的,以展示黑魔法。
这是一个编译时for循环。
/* Compile-time for-loop up to N. */
template <std::size_t N>
struct For {
/* Call f<I>(args...) N times. */
template <typename F, typename... Args>
void operator()(F &&f, Args &&... args) const {
Impl<0, N>()(std::forward<F>(f), std::forward<Args>(args)...);
}
private:
/* Forward declaration. */
template <std::size_t I, std::size_t End>
struct Impl;
/* Base case. Do nothing. */
template <std::size_t End>
struct Impl<End, End> {
template <typename F, typename... Args>
void operator()(F &&, Args &&...) const { /* Do nothing. */ }
}; // Impl<End, End>
/* Recursive case. Call f<I>(args...), then recurse into next step. */
template <std::size_t I, std::size_t End>
struct Impl {
template <typename F, typename... Args>
void operator()(F &&f, Args &&... args) const {
std::forward<F>(f).template operator()<I>(std::forward<Args>(args)...);
Impl<I + 1, End>()(std::forward<F>(f), std::forward<Args>(args)...);
}
}; // Impl<I, End>
}; // For<N>
这是一个简单的用例。
struct Print {
template <std::size_t I>
void operator()(int x, int y) const {
std::cout << "Iteration " << I << ": " << x << ' ' << y << std::endl;
}
}; // Print
For<3>()(Print(), 1, 2);
输出
Iteration 0: 1 2
Iteration 1: 1 2
Iteration 2: 1 2
现在有了这个,我们就可以嵌入这个编译时for循环,就像我们如何嵌套运行时for循环一样。这是使用此For&lt;&gt;的Matrix类。模板。
/* Defines an M by N Matrix, (Row by Col). */
template <std::size_t M, std::size_t N>
class Matrix {
public:
/* Our underlying M by N matrix. */
using Data = std::array<std::array<int, N>, M>;
/* Construct off of M * N arguments. */
template <typename... Args>
Matrix(Args &&... args) {
static_assert(sizeof...(Args) == M * N,
"The number of arguments provided must be M * N.");
ForEach(AssignImpl(),
data_,
std::forward_as_tuple(std::forward<Args>(args)...));
}
/* Print each element out to std::cout. */
void Write(std::ostream &strm) const {
ForEach(WriteImpl(), strm, data_);
}
private:
/* Our outer for loop. Call InnerFor() M times.
Resembles: 'for (std::size_t i = 0 ; i < M; ++i) {' */
template <typename F, typename... Args>
void ForEach(F &&f, Args &&... args) const {
For<M>()(InnerFor(), std::forward<F>(f), std::forward<Args>(args)...);
}
/* Our inner for loop. Call ForBody() N times.
Resembles: 'for (std::size_t j = 0; j < N; ++j) {' */
struct InnerFor {
template <std::size_t I, typename F, typename... Args>
void operator()(F &&f, Args &&... args) const {
For<N>()(ForBody<I>(),
std::forward<F>(f),
std::forward<Args>(args)...);
}
}; // InnerFor
/* The body of our for loop. Call f<I, J>(args...); */
template <std::size_t I>
struct ForBody {
template <std::size_t J, typename F, typename... Args>
void operator()(F &&f, Args &&... args) const {
std::forward<F>(f)
.template operator()<I, J>(std::forward<Args>(args)...);
}
}; // ForBody<I>
/* Given the M by N array and a tuple of length M * N, assign the array. */
struct AssignImpl {
template <std::size_t I, std::size_t J, typename Arg>
void operator()(Data &data, Arg &&arg) const {
data[I][J] = std::get<I * N + J>(std::forward<Arg>(arg));
}
}; // AssignImpl
/* Given an output stream and our data, print the data at (I, J). */
struct WriteImpl {
template <std::size_t I, std::size_t J>
void operator()(std::ostream &strm, const Data &data) const {
strm << data[I][J] << std::endl;
}
}; // WriteImpl
/* Our underlying M by N array. */
Data data_;
}; // Matrix
以下是std::cout
的构建和写作的快速演示。
int main() {
Matrix<3, 2> matrix{101, 102,
201, 202,
301, 302};
matrix.Write(std::cout);
}
答案 3 :(得分:0)
您可以使用std::initializer_list作为构造函数参数,因为您的数组只有int[][]
类型。
Class(std::initializer_list<int> il)
{
if(il.size() < W*H)
throw string("Insufficient elements");//if lesser no. of elements are given.
auto it = il.begin();// iterator to the first element of the list.
for(int i =0;i< W;++i)
{
for(int j =0; j < H;++j)
{
data[i][j] = *it++;// increment the iterator
}
}
}
呼叫网站将如下所示:
Class<3,2> c{1,2,3,4,5,6};
或
Class<3,2> c = {1,2,3,4,5,6};
如果给出更多元素,则丢弃额外的元素。 initializer_list
可以提供类型安全性,如果找到缩小范围,将为您提供诊断。