#c #reference #scope
#c #ссылка #область
Вопрос:
У меня возник конфликт между двумя лучшими практиками, и мне было интересно, есть ли способ получить лучшее из обоих миров.
Мне нужно получить вывод из выбора систем координат, и я хотел бы сделать следующее:
// PSEUDO-CODE
const my_classamp; loads_global();
const my_classamp; loads_local();
GetLoads(COORDINATES coordinates)
{
switch (coordinates)
{
case LOCAL:
const my_classamp; loads = loads_local();
break;
case GLOBAL:
const my_classamp; loads = loads_global();
break;
// etc.
}
loads.write();
}
Использование ссылок const полезно для производительности (и этот код часто вызывается), но если он const, его нельзя установить в пределах разделителя области видимости, такого как оператор switch или оператор if (или, действительно, оператор try, который я хотел сделать раньше).
Я мог бы поместить оператор loads.write(); в коммутатор, но на практике это не просто одна строка, и я ненавижу повторять код. Я мог бы также использовать указатели вместо ссылок (парадигма «const my_class * const my_object»), но это делает код более запутанным, чем использование ссылок.
Есть ли способ использовать ссылку const в окружающем коде или присвоить переменной const, которую я затем не буду / не могу изменить?
Ответ №1:
Если у вас C 11, вы можете использовать лямбда-выражение, чтобы скрыть инициализацию:
GetLoads(COORDINATES coordinates)
{
const my_classamp; loads = [amp;]() -> const my_classamp; {
switch (coordinates)
{
case LOCAL:
return loads_local();
break;
case GLOBAL:
return loads_global();
break;
default:
throw something;
}
}(); // Note the call operator here!
loads.write();
}
Комментарии:
1. Теперь у нас есть лямбда-операторы ?!? Для разработчика LISP, а затем Python, это отличная новость!
2. @MikeSadler они у нас уже некоторое время (4 года) 🙂
3. Я не уверен, как спросить об этом деликатно, но не станет ли пуританин немного придираться к этому? Я пропустил введение макросов, и я не уверен, являются ли они полностью кошерным мейнстримом, или они рассматриваются как своего рода обходной путь…
4. @MikeSadler Какое это имеет отношение к макросам? В любом случае, я сам довольно сильно придерживаюсь принципа «предпочитаю чистоту кода» и нахожу это совершенно нормальным. Если вы имели в виду лямбды вместо макросов, то они, безусловно, часто используются (и поддерживаются многими ведущими специалистами C ).
Ответ №2:
У вас может быть третья функция, которая возвращает const my_classamp;
и выполняет переключение:
const my_classamp; loads_global();
const my_classamp; loads_local();
const my_classamp; GetLoads(COORDINATES coordinates)
{
switch (coordinates)
{
case LOCAL:
return loads_local();
case GLOBAL:
return loads_global();
}
}
void DoSomething(COORDINATES coordinates)
{
const my_classamp; variable = GetLoads(coordinates);
variable.write();
}
Комментарии:
1. Я тоже собирался предложить это. Но что-то должно быть сделано для случая по умолчанию (не ЛОКАЛЬНОГО или ГЛОБАЛЬНОГО).)
2. Это определенно было бы стандартным способом решения проблемы — разделить код на части. Мне было интересно, есть ли способ сделать это «в строке» — особенно в случае, когда есть оператор ‘try’, в котором я чаще всего сталкивался с этой головоломкой.
Ответ №3:
Как насчет этого
const my_classamp; loads = (coordinates == LOCAL) ? loads_local() : loads_global();
непосредственно перед switch
блоком?
Комментарии:
1. К сожалению, мой псевдокод скрыл тот факт, что существует более двух вариантов…
2. Тогда я должен сказать, что Angew, возможно, правильный путь.
Ответ №4:
Для приведенного кода, почему бы не следующее:
GetLoads(COORDINATES coordinates)
{
switch (coordinates)
{
case LOCAL:
loads_local().write();
break;
case GLOBAL:
loads_global().write();
break;
}
}
Не самый модный, но он полностью устраняет проблему локальных переменных. Хорошо, у вас все еще есть временные, но этого нельзя избежать.
Комментарии:
1. Это определенно сработало бы в показанном случае, но я искал более общее решение, где использование переменной может быть слишком длинным для помещения в оператор switch.