Код: Выделить всё
// Pin for Board
struct BoardPin { };
// another kind of pin
struct SpecialPin { };
// a Board that comes with a Pin
class Board
{
// Board's pin
BoardPin m_pin;
public:
// get the Board's pin
constexpr BoardPin &get_pin()
{
return m_pin;
}
};
Код: Выделить всё
// a box of pins of any kind
template
class PinBox
{
std::tuple m_pins;
public:
// construct a PinBox with any kinds of pins
explicit PinBox(PinTypes &...pins) : m_pins{std::tie(pins...)} {};
};
Код: Выделить всё
// a BoardRoom has several Boards
// and a SpecialPin
class BoardRoom
{
// number of boards a room has
static constexpr size_t M_NUM_BOARDS = 4;
// the BoardRoom's Boards
std::array m_boards;
// the BoardRoom's SpecialPin
SpecialPin m_special_pin;
// get the SpecialPin
constexpr SpecialPin& get_special_pin() {
return m_special_pin;
}
public:
// do something that require a PinBox of all the pins
void do_something();
};
Код: Выделить всё
void BoardRoom::do_something() {
PinBox box {
get_special_pin(),
m_boards[0].get_pin(),
m_boards[1].get_pin(),
m_boards[2].get_pin(),
m_boards[3].get_pin()
};
// other stuff
}
(Как я уже сказал, это упрощение, позволяющее сосредоточиться на реальной проблеме: фактические определения разбросаны по дюжине файлов в разных пространствах имен. Небольшой контекст: контакты — это мьютексы, Board — это объект базы данных, PinBox — это std::scoped_lock, а BoardRoom — это «живой» серверный объект, который должен принудительно синхронизироваться для единообразия в реализации гарантий долговечности)
Проблема здесь действительно в том определении PinBox box негибкий и будет неудобным, если M_NUM_BOARDS станет большим (например, 1024; сейчас у меня 16). Кроме того, он подвержен ошибкам, поскольку нет проверки границ рукописного std::array::operator[].
Есть ли лучший способ (который не требует изменения определение PinBox каждый раз при изменении M_NUM_BOARDS)?
Конечно, мы можем ввести get_board_pin(int), например
Код: Выделить всё
// get a pin
constexpr BoardPin& get_board_pin(int idx) {
return m_boards[idx].get_pin();
}
Код: Выделить всё
PinBox box {
get_special_pin(),
get_board_pin(0),
get_board_pin(1),
get_board_pin(2),
get_board_pin(3)
};
Любое решение, каким бы громоздким оно ни было, будет оценено по достоинству.
Подробнее здесь: https://stackoverflow.com/questions/781 ... uctor-from