Проблема не столько в производительности инициализации, сколько в порядке инициализации.Если кто-то использует вашу карту до того, как main
запустится (например, при инициализации переменной области пространства имен), то вы - SOL, потому что вам не гарантируется, что ваша карта была инициализирована до того, как ее использует пользовательская инициализация.
Однако вы можете сделать это во время компиляции.Строковые литералы являются константными выражениями, как и перечислители.Простая структура сложности линейного времени
struct entry {
char const *name;
os value;
};
constexpr entry map[] = {
{ "windows", os::Windows },
{ "linux", os::Linux },
{ "mac", os::Mac }
};
constexpr bool same(char const *x, char const *y) {
return !*x && !*y ? true : (*x == *y && same(x+1, y+1));
}
constexpr os value(char const *name, entry const *entries) {
return same(entries->name, name) ? entries->value : value(name, entries+1);
}
Если вы используете value(a, b)
в контексте константного выражения, а указанное вами имя не существует, вы получите ошибку времени компиляции, потому что вызов функции будетстать непостоянным.
Чтобы использовать value(a, b)
в контексте неконстантных выражений, вам лучше добавить функции безопасности, такие как добавление маркера конца в ваш массив и создание исключения в value
, если вы нажмете маркер конца (функцияВызов будет по-прежнему постоянным выражением, если вы никогда не нажмете маркер конца).