#c #c 11 #templates #c 17 #constexpr
#c #c 11 #шаблоны #c 17 #constexpr
Вопрос:
У меня есть некоторый код, который отлично работал до сих пор, но есть новое изменение, которое нарушает его. Ищу идеи о том, как с этим справиться. Я не эксперт по шаблонам C и обладаю базовыми рабочими знаниями.
namespace foo {
enum {
A1,
A2,
..
AN
};
constexpr int A =
#if defined(SOME_DEFINE1)
A1,
#elif defined(SOME_DEFINE2)
A2,
...
#elif defined(SOME_DEFINEN)
AN
#endif
;
// Then I have some variables that depend on A
template<int> struct var1;
template<>struct var1<A1> { static constexpr auto value = v1; }
template<>struct var1<A2> { static constexpr auto value = v2; }
template<>struct var1<A3> { static constexpr auto value = v3; }
template<int> struct var2;
template<>struct var2<A1> { static constexpr auto value = x1; }
template<>struct var2<A2> { static constexpr auto value = x2; }
template<>struct var2<A3> { static constexpr auto value = x3; }
} // namespace foo
constexpr auto VAR1 = foo::var1<foo::A>::value;
constexpr auto VAR2 = foo::var2<foo::A>::value;
теперь VAR1 и VAR2 используются в нескольких местах. Я понимаю, что весь этот код будет оптимизирован компилятором, и все заработает.
Теперь из-за нового изменения я могу знать только значение ‘A’ во время выполнения и в результате больше не могу объявлять значение постоянным. A будет определяться из значения глобальной переменной где-нибудь. Любые идеи о том, как это реализовать, чтобы я вносил минимальные изменения в свой код.
Допустим, есть gVal, который может быть 1,2 или 3, и на основе этого я хочу установить значение A равным A1, A2 или A3, которые влияют на значения других переменных. Любая помощь приветствуется.
Комментарии:
1.
var1
иvar2
не являются переменными, но вы определяете их со=
знаками, как если бы они были. Ваш код не может скомпилироваться.2. извините, это опечатка. нет знака ‘=’ для var1, var2 … и т. Д
3. у вас не может быть шаблонов во время выполнения, они оцениваются во время компиляции. Ваши переменные VAR1 и VAR2 являются constexpr, поэтому вам придется просмотреть ВЕСЬ ваш код, если вы измените это.
4. По сути, если
A
определяется во время выполнения,VAR1
и т.д. Больше не могут быть определены с использованием шаблонного механизма — который завершается / оценивается во время компиляции, поэтому не может быть отложен до времени выполнения. Я бы, вероятно, просто написал функцию для сопоставления возможных значенийfoo::A
с желаемым результатом. В зависимости от множества других деталей вашего кода (которые вы не показали) возможно, что функция может бытьconstexpr
— что означает, что если ей передана константа, известная во время компиляции, она может быть оценена во время компиляции. Если это возможно, вы можете исключить части механизма шаблонов.
Ответ №1:
Я могу придумать три разумных подхода.
-
Переписать в функции constexpr по частям, полностью протестировав модуль, сохранив старую версию без изменений. Затем переключитесь на версию функций constexpr во время выполнения.
-
Оберните вашу программу (или часть программы) в большой шаблон, который принимает
A
в качестве аргумента. Создайте экземпляр одного из этих шаблонов для каждого допустимогоA
. Напишите интерфейс для этого, который выбирает, какой из этих массивных экземпляров шаблона использовать. -
Рассматривайте это как переопределение кода на другом языке. Используйте существующий код в качестве основы, но не используйте его повторно. c во время компиляции не очень похож на runtime C .
На мой взгляд: 2 является самым быстрым, 3 требует наименьших навыков для достижения прогресса, а 1 занимает больше времени, но с наименьшей вероятностью приведет к новым регрессиям.