Поскольку строковые литералы являются lvalues, вы можете взять их константные ссылки, которые можно использовать в троичной переменной.
// You need to manually specify the size
const char (&foo)[6] = bar ? "lorem" : "ipsum";
// Or (In C++11)
auto foo = bar ? "lorem" : "ipsum";
auto
будет вести себя точно так же (за исключением того, что вам придется указыватьразмер).
Если вы хотите сделать это для строк различной длины, к сожалению, "bool ? const char[x] : const char[y]
" будет только типом массива, если они имеют одинаковый размер (В противном случае они оба распадутся на указатели, ивыражение будет иметь тип const char*
).Чтобы исправить это, вам нужно будет вручную дополнить строку символами \0
(а теперь вы не можете набрать sizeof(foo) - 1
, чтобы получить размер, вам нужно будет сделать strlen(foo)
).
ДляНапример, вместо:
auto foo = bar ? "abc" : "defg"; // foo is a const char*
Вам нужно будет сделать:
auto foo = bar ? "abc\0" : "defg"; // foo is const char(&)[5]
// Note that if `bar` is true, foo is `{'a', 'b', 'c', '\0', '\0'}`
Прежде чем сделать это, учтите, что если вы установите переменные как const char * const
, ваш компиляторболее чем вероятно, оптимизирует их, чтобы они были точно такими же, как если бы они были const char[]
, и, вероятно, также такими же, если бы они были только const char *
(без константы в конце), если вы не измените значение.
Чтобы случайно не получить указатель и быстро потерпеть неудачу, если вы это сделаете, я бы использовал вспомогательную функцию:
#include <cstddef>
template<std::size_t size, std::size_t other_size = size>
constexpr auto conditional(bool condition, const char(&true_case)[size], const char(&false_case)[other_size]) noexcept -> const char(&)[size] {
static_assert(size == other_size, "Cannot have a c-string conditional with c-strings of different sizes");
return condition ? true_case : false_case;
}
// Usage:
auto foo = conditional(bar, "lorem", "ipsum");
Если bar
- постоянная времени компиляции, вы можете изменитьтип foo
в зависимости от значения bar
.Например:
#include <cstddef>
template<bool condition, std::size_t true_size, std::size_t false_size>
constexpr auto conditional(const char(&true_case)[true_size], const char(&false_case)[false_size]) -> typename std::enable_if<condition, const char(&)[true_size]>::type {
return true_case;
}
template<bool condition, std::size_t true_size, std::size_t false_size>
constexpr auto conditional(const char(&true_case)[true_size], const char(&false_case)[false_size]) -> typename std::enable_if<!condition, const char(&)[false_size]>::type {
return false_case;
}
// Or with C++17 constexpr if
template<bool condition, std::size_t true_size, std::size_t false_size>
constexpr auto conditional(const char(&true_case)[true_size], const char(&false_case)[false_size]) -> const char(&)[condition ? true_size : false_size] {
if constexpr (condition) {
return true_case;
} else {
return false_case;
}
}
// Usage:
auto foo = conditional<bar>("dolor", "sit");