Я создаю фабрику для команд, сейчас я могу разделить свои команды на два разных класса: те, для которых требуется адрес, и те, для которых не требуется.
Просто чтобы прояснить, эточасть встроенного проекта, в котором мы решили не использовать динамическое выделение и принести все, что могли, для компиляции времени, поэтому его нужно утверждать во время компиляции.
Я хочу иметь фабричный метод newCommand, которыйпринимает параметр Action и может принимать параметр адреса (если для типа команды требуется адрес) и возвращает команду (в моем случае это буфер с предопределенным размером для каждого из типов команд).
Oneя попробовал перегрузку функций:
struct Driver
{
enum Action
{
PAGE_PROGRAM = 0x2, // requires address
SECTOR_ERASE = 0x20, // requires address
WRITE_DISABLE = 0x4, // doesn't require address
WRITE_ENABLE = 0x6 // doesn't require address
};
};
struct DriverCommandFactory
{
static dummy_buffer<1> newCommand(Driver::Action command)
{
dummy_buffer<1> ret;
return ret;
}
static dummy_buffer<4> newCommand(Driver::Action command, uint32_t address)
{
dummy_buffer<4> ret;
return ret;
}
};
Но у этого подхода есть «проблема», пользователь (фабричный потребитель) может по-прежнему вызывать версию newCommand только с одним параметром, передающим действие, которому НУЖЕН адрес,Опять же, я мог бы проверить это во время выполнения, но это не то, что я хочу.
Еще одна вещь, которую я попробовал, - это введение другого перечисления, называемого CommandType, и использование явной (полной) специализации шаблона.:
template <Driver2::CommandType TYPE>
struct DriverCommandFactory2;
template <>
struct DriverCommandFactory2 <Driver2::CommandType::REQUIRES_ADDRESS>
{
static dummy_buffer<4> newCommand(Driver::Action command, uint32_t address)
{
dummy_buffer<4> ret;
return ret;
}
};
template <>
struct DriverCommandFactory2 <Driver2::CommandType::DOESNT_REQUIRE_ADDRESS>
{
static dummy_buffer<1> newCommand(Driver::Action command)
{
dummy_buffer<1> ret;
return ret;
}
};
Этот «не» позволяет пользователю вызывать неправильную версию метода, чего не могло сделать предыдущее решение.Но это порождает другую проблему, заставляет пользователя указывать тип команды в качестве аргумента шаблона, что является избыточным, поскольку само действие достаточно, чтобы это знать.
Итак, есть ли способ, которым я могу предотвратитьпользователь не вызвал неправильный метод, не заставив его элегантно указать аргумент шаблона?Опять же, это нужно проверить во время компиляции.
Если это поможет, у меня есть компилятор C ++ 17.