Перегрузка функций с помощью фиктивных структур и специализация шаблоновC++

Программы на C++. Форум разработчиков
Ответить Пред. темаСлед. тема
Anonymous
 Перегрузка функций с помощью фиктивных структур и специализация шаблонов

Сообщение Anonymous »

Я проводил рефакторинг C++ и наткнулся на несколько фиктивных структур, используемых для различения перегруженных функций. Я подумываю заменить это на специализацию шаблона, но сначала хочу полностью понять последствия.
У нас есть класс перечисления, который часто используется для принятия решения о том, как обрабатывать какое-либо значение:
р>

Код: Выделить всё

enum class OptionEnum : int {
optionA,
optionB
};

void foo( const int val, const OptionEnum option ){
if( option == OptionEnum::optionA ){
doSomething( val );
} else if ( option == OptionEnum::optionB ) {
doSomethingElse( val );
} else {
throw std::invalid_argument( "Unsupported Option" );
}

doMoreStuff();
}
Однако, когда функция особенно сложна, текущий код использует перегрузку и некоторые фиктивные структуры для получения правильного разрешения перегрузки:

Код: Выделить всё

struct OptionsStruct{};
static constexpr struct OptionStructA : OptionsStruct{} optionA;
static constexpr struct OptionStructB : OptionsStruct{} optionB;

void foo( const int val, const OptionStructA & ){
doSomething( val );
}

void foo( const int val, const OptionStructB & ){
doSomethingElse( val );
}
Это часто делается с помощью некоторой промежуточной шаблонной функции, которой не важно, какая опция используется, но ей необходимо знать, какую перегрузку вызывать:

Код: Выделить всё

template < typename OptionStructAorB >
void bar( const int val, const OptionStructAorB option ){
int result = processVal( val );
foo( result, option );
}

void baz( const int val, const OptionEnum option ){
if ( option == OptionEnum::optionA ){
bar( val, optionA );
} else if ( option == OptionEnum::optionB ) {
bar( val, optionB );
} else {
throw std::invalid_argument( "Unsupported Option in baz" );
}
}

int main(int argc, char* argv[]) {
const int inputVal = std::atoi(argv[1]);
const std::string optionString = argv[2];

OptionEnum inputOption;
if ( optionString == "a" ){
inputOption = OptionEnum::optionA;
} else if ( optionString == "b" ) {
inputOption = OptionEnum::optionB;
} else {
std::cout (const int val){
doSomethingElse(val);
}

template< OptionEnum option >
void bar(const int val){
int result = processVal(val);
foo(result);
}

void baz( const int val, const OptionEnum option ){
if ( option == OptionEnum::optionA ){
bar( val );
} else if ( option == OptionEnum::optionB ) {
bar( val );
} else {
throw std::invalid_argument( "Unsupported Option in baz" );
}
}
Помимо самоуверенных опасений по поводу стиля и читабельности, есть ли какие-либо конкретные преимущества у исходного подхода с фиктивными структурами по сравнению с подходом специализации шаблонов с точки зрения производительности, безопасности типов и удобства сопровождения (специфично для C) ++17)? Могут ли возникнуть проблемы с удобством обслуживания при добавлении нового значения перечисления, которое, например, хуже в новом подходе?
(Да, foo(), вероятно, вообще не следует перегружать, и нам следует просто есть fooA() и fooB(), но кодовая база - это максимум спагетти, и это компромисс)

Подробнее здесь: https://stackoverflow.com/questions/787 ... ialisation
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C++»