【问题标题】:CMake: `call to non-‘constexpr’ function ‘_Tp std::accumulate`CMake:`调用非'constexpr'函数'_Tp std::accumulate`
【发布时间】:2021-06-29 11:52:36
【问题描述】:

在 CMake 项目中,我得到了输出:

[main] Building folder: cmake-test 
[build] Starting build
[proc] Executing command: /usr/bin/cmake --build /home/jonathan/Projects/cmake-test/build --config Debug --target all -- -j 14
[build] Scanning dependencies of target hello_cmake
[build] [ 50%] Building CXX object CMakeFiles/hello_cmake.dir/main.cpp.o
[build] /home/jonathan/Projects/cmake-test/main.cpp: In function ‘int main()’:
[build] /home/jonathan/Projects/cmake-test/main.cpp:25:43: error: ‘constexpr size_t pushConstantsSize(const std::array<std::variant<unsigned int, float>, NumPushConstants>&) [with long unsigned int NumPushConstants = 1; size_t = long unsigned int]’ called in a constant expression
[build]    25 |     constexpr size_t x = pushConstantsSize(pushConstants);
[build]       |                          ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
[build] /home/jonathan/Projects/cmake-test/main.cpp:9:18: note: ‘constexpr size_t pushConstantsSize(const std::array<std::variant<unsigned int, float>, NumPushConstants>&) [with long unsigned int NumPushConstants = 1; size_t = long unsigned int]’ is not usable as a ‘constexpr’ function because:
[build]     9 | constexpr size_t pushConstantsSize(std::array<std::variant<uint32_t,float>,NumPushConstants> const& pushConstants) {
[build]       |                  ^~~~~~~~~~~~~~~~~
[build] /home/jonathan/Projects/cmake-test/main.cpp:14:47: error: call to non-‘constexpr’ function ‘_Tp std::accumulate(_InputIterator, _InputIterator, _Tp, _BinaryOperation) [with _InputIterator = const std::variant<unsigned int, float>*; _Tp = long unsigned int; _BinaryOperation = pushConstantsSize(const std::array<std::variant<unsigned int, float>, NumPushConstants>&) [with long unsigned int NumPushConstants = 1; size_t = long unsigned int]::<lambda(std::size_t, auto:23)>]’
[build]    14 |     return static_cast<size_t>(std::accumulate(pushConstants.cbegin(),pushConstants.cend(),
[build]       |                                ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build]    15 |         std::size_t{ 0 },
[build]       |         ~~~~~~~~~~~~~~~~~                      
[build]    16 |         [size_fn](std::size_t acc, auto const var) { return acc + std::visit(size_fn,var); }
[build]       |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build]    17 |     ));
[build]       |     ~                                          
[build] make[2]: *** [CMakeFiles/hello_cmake.dir/build.make:63: CMakeFiles/hello_cmake.dir/main.cpp.o] Error 1
[build] make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/hello_cmake.dir/all] Error 2
[build] make: *** [Makefile:84: all] Error 2
[build] Build finished with exit code 2

IntelliSense 给出的错误:

main.cpp:

#include <numeric>
#include <array> // std::array
#include <numeric> // std::accumulate
#include <variant> // std::variant
#include <stdint.h> // uint32_t
#include <iostream>

template <size_t NumPushConstants>
constexpr size_t pushConstantsSize(std::array<std::variant<uint32_t,float>,NumPushConstants> const& pushConstants) {
    auto size_fn = [](auto const& var) -> size_t {
        using T = std::decay_t<decltype(var)>;
        return sizeof(T);
    };
    return static_cast<size_t>(std::accumulate(pushConstants.cbegin(),pushConstants.cend(),
        std::size_t{ 0 },
        [size_fn](std::size_t acc, auto const var) { return acc + std::visit(size_fn,var); }
    ));
}

int main() {
    constexpr size_t num = 1;
    static std::array<std::variant<uint32_t,float>,num> const pushConstants = {
        uint32_t {  1 }
    };
    constexpr size_t x = pushConstantsSize(pushConstants);
    std::cout << "size:" << x <<std::endl;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)
project (hello_cmake)
set(CMAKE_CXX_STANDARD 20)
add_executable(${PROJECT_NAME} main.cpp)

最小的可重现示例项目 zip:https://drive.google.com/file/d/1b33hWUkLgQh8knvKV5k3_jDq1uJIUuTv/view?usp=sharing

https://gcc.godbolt.org/z/esPd87r4o 实现相同的代码时,它可以工作,这并不意外,因为这可能是 CMake 配置的问题。

对于std::accumulateconstexpr 实现,我使用的是 CPP 20 和 GCC 10.2.0,因为它在以下要求中指定:

constexpr 用于数值算法

在:https://en.cppreference.com/w/cpp/compiler_support

CMakeLists.txt 包括set(CMAKE_CXX_STANDARD 20)

查看我系统上安装的编译器:

jonathan@jonathan-MS-7B22:~$ gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

jonathan@jonathan-MS-7B22:~$ gcc-10 --version
gcc-10 (Ubuntu 10.2.0-5ubuntu1~20.04) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

jonathan@jonathan-MS-7B22:~$ g++ --version
g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

jonathan@jonathan-MS-7B22:~$ g++-10 --version
g++-10 (Ubuntu 10.2.0-5ubuntu1~20.04) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

jonathan@jonathan-MS-7B22:~$ 

已安装 CMake:

jonathan@jonathan-MS-7B22:~$ cmake --version
cmake version 3.16.3

CMake suite maintained and supported by Kitware (kitware.com/cmake).
jonathan@jonathan-MS-7B22:~$

为了方便起见,我正在使用 Visual Studio 代码 CMake Tools 扩展,设置如下:

目前我最好的猜测是某些方面默认使用gcc 而不是gcc-10,这会导致这个问题影响整个项目,但我不知道这可能在哪里或如何解决它。

我不知道该怎么做,任何帮助将不胜感激,感谢您阅读本文。

更新

我相信我已经找到了错误的来源,在重新配置项目时我得到了输出:

[main] Configuring folder: cmake-test 
[driver] Removing /home/jonathan/Projects/cmake-test/build/CMakeCache.txt
[driver] Removing /home/jonathan/Projects/cmake-test/build/CMakeFiles
[proc] Executing command: /usr/bin/cmake --no-warn-unused-cli -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=/bin/gcc-10 -H/home/jonathan/Projects/cmake-test -B/home/jonathan/Projects/cmake-test/build -G "Unix Makefiles"
[cmake] Not searching for unused variables given on the command line.
[cmake] -- The C compiler identification is GNU 10.2.0
[cmake] -- The CXX compiler identification is GNU 9.3.0
[cmake] -- Check for working C compiler: /bin/gcc-10
[cmake] -- Check for working C compiler: /bin/gcc-10 -- works
[cmake] -- Detecting C compiler ABI info
[cmake] -- Detecting C compiler ABI info - done
[cmake] -- Detecting C compile features
[cmake] -- Detecting C compile features - done
[cmake] -- Check for working CXX compiler: /bin/c++
[cmake] -- Check for working CXX compiler: /bin/c++ -- works
[cmake] -- Detecting CXX compiler ABI info
[cmake] -- Detecting CXX compiler ABI info - done
[cmake] -- Detecting CXX compile features
[cmake] -- Detecting CXX compile features - done
[cmake] -- Configuring done
[cmake] -- Generating done
[cmake] -- Build files have been written to: /home/jonathan/Projects/cmake-test/build

注释行是The CXX compiler identification is GNU 9.3.0,我认为这是最终导致错误的原因,我需要将The CXX compiler 设置为10.2.0。我不确定如何更改。

【问题讨论】:

  • “所以我认为简单地提供 .zip 文件是最简单的” 呃,不。请提供minimal reproducible example。您的构建还会发出compile_commands.json,因此您可以检查该文件中的标志/编译器是否设置正确。
  • I can't reproduce your error here. 我不太倾向于下载和翻阅 zip 文件而不是从问题中获取信息,所以我不知道这与您的实际代码有什么不同,但是我已经在持续评估中使用std::accumulate 成功演示了 GCC 10.2。
  • 我会删除 CMake 缓存文件夹重新配置它。 vscode 的 CMake 插件中内置了一个命令来执行此操作。
  • @Barry 更新为使用最少的可重现示例。
  • @chris 更新为使用最少的可重现示例。

标签: c++ gcc cmake c++20


【解决方案1】:

作为更新部分注释The CXX compiler identification is GNU 9.3.0 来解决此问题,您可以执行set(CMAKE_CXX_COMPILER "/usr/bin/g++-10")(来自https://stackoverflow.com/a/22619145/4301453)并重新加载项目。

这似乎有效。

虽然我不确定这是最好的答案,但它现在有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-10
    • 2019-11-11
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    • 2017-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多