Jon*_*Mee 6 c++ arrays ternary variable-initialization char-pointer
我问一个问题,它并没有得到一个非常明确的答案,但看完后这篇文章,我开始喜欢const char[]到const char*。
我在用三元初始化时遇到了困难。鉴于const bool bar,我试过:
const char foo[] = bar ? "lorem" : "ipsum" 这给了我错误:错误:初始化程序无法确定的大小
foo
const char foo[] = bar ? { 'l', 'o', 'r', 'e', 'm', '\0' } : { 'i', 'p', 's', 'u', 'm', '\0' } 这给了我错误:错误:
{令牌前的预期主表达式
有没有办法const char []用三元初始化 a ,还是我必须切换到const char*这里?
由于字符串文字是左值,因此您可以获取它们的 const 引用,这可以在三元中使用。
// You need to manually specify the size
const char (&foo)[6] = bar ? "lorem" : "ipsum";
// Or (In C++11)
auto foo = bar ? "lorem" : "ipsum";
Run Code Online (Sandbox Code Playgroud)
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*
Run Code Online (Sandbox Code Playgroud)
你必须这样做:
auto foo = bar ? "abc\0" : "defg"; // foo is const char(&)[5]
// Note that if `bar` is true, foo is `{'a', 'b', 'c', '\0', '\0'}`
Run Code Online (Sandbox Code Playgroud)
在必须执行此操作之前,请考虑一下,如果将变量设置为const char * const,编译器很可能会将它们优化为与 完全相同,如果它们只是(最后没有 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");
Run Code Online (Sandbox Code Playgroud)
如果是编译时常量,您可以根据 的值bar更改 的类型。例如:foobar
#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");
Run Code Online (Sandbox Code Playgroud)