使用 constexpr 作为 std::array size
Using constexpr as std::array size
我有以下代码使用constexpr
作为数组大小。
#include <array>
template <size_t size>
constexpr size_t
GetSize(const char(&format)[size])
{
// Iterate over format array and compute a value.
size_t count = 0;
for (size_t i = 0; i < size; ++i)
{
if (format[i] == '%')
{
++count;
}
}
return count;
}
template <size_t size>
constexpr auto
GetArray(const char(&format)[size])
{
constexpr size_t arraySize = GetSize(format);
return std::array<char, arraySize>();
}
int main(int argc, char** argv)
{
static_assert(GetArray("hello").size() == 12, "failed");
}
但是,这无法在VS2019下编译,并出现以下错误
error C2131: expression did not evaluate to a constant
message : failure was caused by a read of a variable outside its lifetime
message : see usage of 'format'
message : see reference to function template instantiation 'auto GetArray<6>(const char (&)[6])' being compiled
这是编译器错误吗?如果是这样,是否有解决方法?
constexpr 函数的问题在于,你可以同时调用 constexpr 参数和非 constexpr 参数:
int constexpr f(int n)
{
return ++n;
}
int constexpr n0 = 7;
int n1; std::cin >> n1;
f(n0); // result IS constexpr
f(n1); // result is NOT constexpr, just an ordinary int
由于这个特性,函数参数本身不能是constexpr,或者更准确地说,不能在constexpr上下文中使用。所以在你的函数中也是如此:
constexpr size_t arraySize = getSize(format);
// ^ cannot be used as constexpr, even if
// constexpr has been passed to, so result
// not either (the f(n1) case above)
你可以稍微修改一下你的第二个函数:
template <size_t Size>
constexpr auto
getArray()
{
return std::array<char, Size>();
}
并像使用它一样使用
int main(int argc, char** argv)
{
static_assert(getArray<getSize("hello")>().size() == 0, "failed");
return 0;
}
当然,现在看起来相当丑陋,不过,您可能会躲在宏后面:
#define myGetArray(STRING) getArray<getSize(STRING)>()
或者干脆
#define getArray(STRING) std::array<char, getSize(STRING)>()
我不知道您是否绝对需要GetSize()
函数用于其他目的,但是在您的 GetArray 中,您已经可以访问数组的长度,因此您可以这样做:
#include <array>
template <std::size_t N>
constexpr auto
GetArray(const char(&format)[N])
{
return std::array<char, N*2>{};
}
int main(int argc, char** argv)
{
static_assert(GetArray("hello").size() == 12, "failed");
}
这是一个 C++17 的工作解决方案,使用 lambda 将 char 数组包装为 constexpr。
#include <array>
#include <string>
template <typename Char_Array_Holder>
constexpr size_t GetSize(Char_Array_Holder holder)
{
// Iterate over format array and compute a value.
constexpr std::string_view format = holder();
size_t count = 0;
for (char c : format)
{
if (c == '%')
{
++count;
}
}
return count;
}
template <typename Char_Array_Holder>
constexpr auto GetArray(Char_Array_Holder holder)
{
constexpr size_t arraySize = GetSize(holder);
return std::array<char, arraySize>();
}
#define hold(msg) []() { return msg; }
int main(int argc, char** argv)
{
static_assert(GetArray(hold("hello")).size() == 0, "failed...");
static_assert(GetArray(hold("h%ello")).size() == 1, "failed...");
static_assert(GetArray(hold("h%el%%lo")).size() == 3, "failed...");
}
改编自编译时字符串解析,您可以阅读以获取更多信息
相关文章:
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 大于65535的C++数组[size]引发不一致的溢出
- 为什么(-1)%vector::size()总是返回0
- 从 std::string 到 std::array<char,size> 的 memcopy 额外数据是否是一种未定义的行为?
- 为什么我必须在初始化 std::array<SomeStruct, size> 时指定每个项目的类型C++
- 如何在 JniWrapper 中将 Java ArrayList<float[]> 映射到C++ Vector<array<float,size>>?
- 使用 constexpr 作为 std::array size
- 警告的原因是什么:"when type is in parentheses, array cannot have dynamic size"?
- std::span.size() vs array/vector size
- std::array::max_size 和 std::array::size 给出不同结果的示例
- 为什么 std::array::size 不是静态的?
- 具有恒定大小数组的警告"ISO C++ forbids variable-size array"
- 为什么 std::array::size constexpr 具有简单类型(int、double、..),而不是 std
- 如何在 c++11 中使用容器 std::array<type, size> 用于多维数组?
- 使用 std::array::size 实例化 std::array 时出错
- 为什么我会得到"cannot allocate an array of constant size 0"?
- 在比较 array.size() 与负值时获得 if 条件的意外行为
- ARRAY[T, SIZE]合适的默认构造函数可用
- c++中的快速排序array.size()错误
- 从(bad) array[size]移动到array = new float[size]