c++ - 使用 `std::accumulate` 和 constexpr
问题描述
原来的
给定 astd::array<std::variant<>>
我得到总字节大小(例如{float,float,uint32_t}=4+4+4=12
),然后我想以 a 的形式获取数组void*
(传递给 Vulkan)。
我不相信我需要为此进行堆分配,尽管我坚持如何将计算出的大小作为模板参数传递。
Repl:https ://repl.it/@JonathanWoollet/HumongousDistinctDefinitions
错误:
> clang++-7 -pthread -std=c++17 -o main main.cpp
main.cpp:42:30: error: constexpr variable 'size' must be initialized by a
constant expression
constexpr uint32_t const size = arrSize<num>(arr);
^ ~~~~~~~~~~~~~~~~~
main.cpp:17:34: note: non-constexpr function 'accumulate<const
std::variant<unsigned int, float> *, unsigned long, (lambda at
main.cpp:19:9)>' cannot be used in a constant expression
return static_cast<uint32_t>(std::accumulate(arr.cbegin(),arr.cend(),
^
main.cpp:42:37: note: in call to 'arrSize(arr)'
constexpr uint32_t const size = arrSize<num>(arr);
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_numeric.h:146:5: note:
declared here
accumulate(_InputIterator __first, _InputIterator __last, _Tp __init,
^
main.cpp:44:21: error: no matching function for call to 'toVoidPtr'
void* voidArr = toVoidPtr<num,size>(arr);
^~~~~~~~~~~~~~~~~~~
main.cpp:25:7: note: candidate template ignored: invalid explicitly-specified
argument for template parameter 'Size'
void* toVoidPtr(std::array<std::variant<uint32_t,float>,Num> const& arr) {
^
2 errors generated.
compiler exit status 1
(用 C++20 编译会导致同样的错误)
我已经看到编译时等同于 std::accumulate()但https://en.cppreference.com/w/cpp/algorithm/accumulate清楚地显示了一个constexpr
定义:
template< class InputIt, class T, class BinaryOperation >
constexpr T accumulate( InputIt first, InputIt last, T init,
BinaryOperation op );
我通过以下方式获得尺寸:
template <uint32_t Num>
constexpr uint32_t arrSize(std::array<std::variant<uint32_t,float>,Num> const& arr) {
auto var_size = [](auto const& var) -> size_t {
using T = std::decay_t<decltype(var)>;
return sizeof(T);
};
return static_cast<uint32_t>(std::accumulate(arr.cbegin(),arr.cend(),
std::size_t{ 0 },
[var_size](std::size_t acc, auto const var) { return acc + std::visit(var_size,var); }
));
}
我转换为void*
:
template <uint32_t Num, uint32_t Size>
void* toVoidPtr(std::array<std::variant<uint32_t,float>,Num> const& arr) {
size_t byteCounter = size_t{0};
std::array<std::byte,Size> bytes;
std::for_each(arr.cbegin(),arr.cend(), [&](auto const& var) {
std::visit([&] (auto const& var) {
using T = std::decay_t<decltype(var)>;
std::memcpy(bytes.data()+byteCounter,static_cast<void const*>(&var),sizeof(T));
byteCounter += sizeof(T);
},var);
});
return static_cast<void*>(bytes.data);
}
我想遵循如下命令:
int main() {
std::cout << "Hello World!\n";
const uint32_t num = 3U;
std::array<std::variant<uint32_t,float>,num> arr = { 1.34F, 3.76F, 124U };
constexpr uint32_t const size = arrSize<num>(arr);
std::cout << "size: " << size << std::endl;
void* voidArr = toVoidPtr<num,size>(arr);
}
我不确定我在这里缺少什么,我似乎无法弄清楚。我真的很感激任何帮助。
(我缺少任何东西,请发表评论,我会尝试添加它)
与gcc 10.2.0
&c++20
在按照Werner Henze的建议更新以使用兼容的构建工具并更新我的本地项目以使用gcc 10.2.0
Henze 之后,c++20
我得到了不同的错误。
[build] In file included from C:\Users\jonat\Projects\gpu_blas\c++\test\ExampleTests.cpp:2:
[build] c:\users\jonat\projects\gpu_blas\c++\example.hpp: In instantiation of 'ComputeApp<NumPushConstants>::ComputeApp(const char*, uint32_t, const uint32_t*, float**, std::array<std::variant<unsigned int, float>, NumPushConstants>, std::array<unsigned int, 3>, std::array<unsigned int, 3>) [with unsigned int NumPushConstants = 1; uint32_t = unsigned int]':
[build] C:\Users\jonat\Projects\gpu_blas\c++\test\ExampleTests.cpp:41:5: required from here
[build] c:\users\jonat\projects\gpu_blas\c++\example.hpp:367:95: in 'constexpr' expansion of 'Utility::pushConstantsSize<1>(pushConstant)'
[build] c:\users\jonat\projects\gpu_blas\c++\example.hpp:102:53: in 'constexpr' expansion of 'std::accumulate<const std::variant<unsigned int, float>*, long long unsigned int, Utility::pushConstantsSize<1>::<lambda(std::size_t, auto:43)> >((& pushConstants)->std::array<std::variant<unsigned int, float>, 1>::cbegin(), (& pushConstants)->std::array<std::variant<unsigned int, float>, 1>::cend(), 0, <lambda closure object>Utility::pushConstantsSize<1>::<lambda(std::size_t, auto:43)>{<lambda closure object>Utility::pushConstantsSize<1>::<lambda(const auto:42&)>()})'
[build] c:\users\jonat\projects\gpu_blas\c++\example.hpp:367:38: error: 'pushConstant' is not a constant expression
[build] 367 | constexpr uint32_t const sizeTester = Utility::pushConstantsSize<NumPushConstants>(pushConstant);
[build] | ^~~~~~~~~~
[build] c:\users\jonat\projects\gpu_blas\c++\example.hpp: In instantiation of 'ComputeApp<NumPushConstants>::ComputeApp(const char*, uint32_t, const uint32_t*, float**, std::array<std::variant<unsigned int, float>, NumPushConstants>, std::array<unsigned int, 3>, std::array<unsigned int, 3>) [with unsigned int NumPushConstants = 3; uint32_t = unsigned int]':
[build] C:\Users\jonat\Projects\gpu_blas\c++\test\ExampleTests.cpp:849:5: required from here
[build] c:\users\jonat\projects\gpu_blas\c++\example.hpp:367:95: in 'constexpr' expansion of 'Utility::pushConstantsSize<3>(pushConstant)'
[build] c:\users\jonat\projects\gpu_blas\c++\example.hpp:102:53: in 'constexpr' expansion of 'std::accumulate<const std::variant<unsigned int, float>*, long long unsigned int, Utility::pushConstantsSize<3>::<lambda(std::size_t, auto:43)> >((& pushConstants)->std::array<std::variant<unsigned int, float>, 3>::cbegin(), (& pushConstants)->std::array<std::variant<unsigned int, float>, 3>::cend(), 0, <lambda closure object>Utility::pushConstantsSize<3>::<lambda(std::size_t, auto:43)>{<lambda closure object>Utility::pushConstantsSize<3>::<lambda(const auto:42&)>()})'
[build] c:\users\jonat\projects\gpu_blas\c++\example.hpp:367:38: error: 'pushConstant' is not a constant expression
[build] mingw32-make[2]: *** [test\CMakeFiles\ExampleTests.dir\build.make:82: test/CMakeFiles/ExampleTests.dir/ExampleTests.cpp.obj] Error 1
[build] mingw32-make[1]: *** [CMakeFiles\Makefile2:315: test/CMakeFiles/ExampleTests.dir/all] Error 2
[build] mingw32-make: *** [makefile:159: all] Error 2
[build] Build finished with exit code 2
我在这里做了更多的游戏,但我找不到问题,再次感谢任何帮助。
由于我无法提供 Repl 以最低限度地重现此问题,因此这里是 CMake 项目的链接,当前分支会产生这些错误:https ://github.com/JonathanWoollett-Light/gpu_blas/tree/Compiler-update/c%2B %2B
解决方案
cppreference accumulate说这accumulate
只是constexpr
从 C++20 开始,而不是在 C++17 中。所以你需要切换到 C++20。
如果您想知道哪个编译器已经支持constexpr accumulate
,可以查看cppreference 编译器支持并搜索“constexpr for numeric algorithms”/P1645R1。例如,对于 clang,它需要 libc++ 12。
推荐阅读
- flutter - 屏幕不显示颤动
- powershell - 记录cmd.exe的命令行
- apache-spark - Spark Dataframe 中的嵌套数据透视表
- angular7 - Angular http 获取 Date 属性的错误数据类型
- python - 为什么在将 LAB 空间图像写入目录时出现黑色图像?
- c# - c# GUI 在启动控制台应用程序后冻结
- java - android Draw Text with text size change and translate in canvas
- sql - SQL 查询以选择记录,该记录检查至少一条具有给定条件的有效记录
- java - 我需要明确插入弹簧核心模块吗?
- python-3.x - 在 tensorflow 1.12 中读取 uint16 图像的奇怪问题