назначить шаблонную переменную во время выполнения

#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:

Я могу придумать три разумных подхода.

  1. Переписать в функции constexpr по частям, полностью протестировав модуль, сохранив старую версию без изменений. Затем переключитесь на версию функций constexpr во время выполнения.

  2. Оберните вашу программу (или часть программы) в большой шаблон, который принимает A в качестве аргумента. Создайте экземпляр одного из этих шаблонов для каждого допустимого A . Напишите интерфейс для этого, который выбирает, какой из этих массивных экземпляров шаблона использовать.

  3. Рассматривайте это как переопределение кода на другом языке. Используйте существующий код в качестве основы, но не используйте его повторно. c во время компиляции не очень похож на runtime C .

На мой взгляд: 2 является самым быстрым, 3 требует наименьших навыков для достижения прогресса, а 1 занимает больше времени, но с наименьшей вероятностью приведет к новым регрессиям.