Цель состоит в том, чтобы иметь систему флагов Feature без затрат времени исполнения. Простое решение C99:
C99:
#include <stdio.h>
#define flag_1 1
int main()
{
#if flag_1
printf("Active\n");
#else
printf("InActive\n");
#endif
return 0;
}
не то, что решение C++ 17 кажется элегантным:
#include <iostream>
constexpr bool tag_flag_1 = true;
constexpr bool tag_flag_2 = true;
int main()
{
if constexpr(tag_flag_1)
{
std::cout << "Active" << std::endl;
}
else
{
std::cout << "InActive" << std::endl;
}
return 0;
}
Но не работает, так как конструкция if if constexpr действует только в том случае, если существует конструкция if. Например, этот код недействителен:
if constexpr(tag_flag_1)
{
class foo
{
};
}
в то время как это:
#if tag_flag_1
class foo
{
};
#endif
Проблема с решением C99:
набрав:
if constexpr(flag_not_exists)
приведет к ошибке компиляции, тогда как:
#if flag_not_exists
Не буду.
Конечно, всегда можно написать это альтернативное громоздкое решение в C99:
#include "stdio.h"
#define flag_1 0
int main()
{
#if flag_1
printf("Active\n");
#elif defined(flag_1)
printf("InActive\n");
#else
#error undefined_flag
#endif
return 0;
}
Вопрос:
Есть ли элегантный способ гарантировать, что использование флага функции несуществующего (неправильно написанного) экземпляра приводит к ошибке компиляции?
Это важно для решения:
- Не требовать постоянной разработки дополнительного "else #error" от разработчика. Мы все ленивы...
- Чтобы иметь 0 временных затрат
- Для поддержки логических операций "#if (feature_1 || feature_2) &&! Feature_3"
- Точность "Feature Flag System": при разработке новой функции вы можете изменить подпись функции, добавить член в класс, изменить тип переменной, добавить новый класс... Это буквально эквивалентно наличию двух ветвей (главная и особенность), живущих в одном файле. Переход от одного к другому путем включения и выключения флага. Любая модификация кода может быть отмечена функцией!
Мне очень интересно узнать о возможном шаблоне и/или макро-ориентированном решении.
Изменить комментарий:
Простое решение с C99 было бы неплохо. В настоящее время наше программное обеспечение компилируется с помощью компилятора Cpp11. Но даже решение Cpp17 было бы неплохо для более позднего... любое решение хорошо, тем лучше обратная совместимость лучше (поскольку все больше людей могут ее использовать!).