Here's an example of using a factory lambda to produce the initial cells in the Table's constructor. Refer to main
function where the lambda is located, and the Table constructor for how it is used.
I do not know what your code looks like, so I just wrap each cell into an object_t and put that into the Table.
#include <cstdint>
#include <functional>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
// Not idempotent. Should be last include.
#include <cassert>
using std::cout;
using std::function;
using std::make_shared;
using std::move;
using std::ostream;
using std::shared_ptr;
using std::size_t;
using std::string;
using std::stringstream;
using std::vector;
namespace {
template <typename T>
void draw_right_justified(T const& x, ostream& out, size_t width) {
stringstream ss;
ss << x;
string s = ss.str();
size_t pad_width = s.length() < width ? width - s.length() : 1;
out << string(pad_width, ' ') << s;
}
class object_t {
public:
template <typename T>
object_t(T x) : self_{make_shared<model<T>>(move(x))}
{ }
friend void draw_right_justified(object_t const& x, ostream& out, size_t width) {
x.self_->draw_right_justified_thunk(out, width);
}
private:
struct concept_t {
virtual ~concept_t() = default;
virtual void draw_right_justified_thunk(ostream&, size_t) const = 0;
};
template <typename T>
struct model : concept_t {
model(T x) : data_{move(x)} { }
void draw_right_justified_thunk(ostream& out, size_t width) const {
draw_right_justified(data_, out, width);
}
T data_;
};
shared_ptr<const concept_t> self_;
};
class Table {
size_t col;
size_t row;
// data will be constructed with col_ * row_ entries.
vector<object_t> data;
public:
using object_factory = function<object_t(size_t, size_t)>;
Table(size_t col_, size_t row_, object_factory& fn);
auto operator()(size_t x, size_t y) const -> object_t;
void display(ostream& out) const;
};
Table::Table(size_t col_, size_t row_, Table::object_factory& fn)
: col{col_}, row{row_}
{
data.reserve(col * row);
for (size_t y = 0; y < row; ++y) {
for (size_t x = 0; x < row; ++x) {
data.emplace_back(fn(x, y));
}
}
}
object_t Table::operator()(size_t x, size_t y) const {
assert(x < col);
assert(y < row);
return data[y * row + x];
}
void Table::display(ostream& out) const {
auto const& self = *this;
for (size_t y = 0; y < row; ++y) {
for (size_t x = 0; x < col; ++x) {
draw_right_justified(self(x, y), out, 8);
}
out << "
";
}
}
struct empty_t {};
void draw_right_justified(empty_t, ostream& out, size_t width) {
string s = "(empty)";
size_t pad_width = s.length() < width ? width - s.length() : 1;
out << string(pad_width, ' ') << s;
}
struct bunny { string name; };
void draw_right_justified(bunny const& bunny, ostream& out, size_t width) {
auto const& s = bunny.name;
size_t pad_width = s.length() < width ? width - s.length() : 1;
out << string(pad_width, ' ') << s;
}
} // anon
int main() {
Table::object_factory maker = [](size_t x, size_t y) {
if (x == 0 && y == 1) return object_t{bunny{"Bugs"}};
if (x == 0 && y == 0) return object_t{empty_t{}};
if (x == y) return object_t{string("EQUAL")};
return object_t{x * y};
};
auto table = Table{3, 5, maker};
table.display(cout);
}
Output...
(empty) 0 0
Bugs EQUAL 2
0 2 EQUAL
0 3 6
0 4 8
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…