Поскольку строковые литералы являются lvalue, вы можете использовать константные ссылки на них, которые можно использовать в троичном коде.
// 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");
person
Artyer
schedule
11.12.2018
bar
константой времени компиляции? - person NathanOliver   schedule 11.12.2018bar
была константой времени компиляции, я бы согласился. - person Jonathan Mee   schedule 11.12.2018