C++ 模板专业化更改 constexpr 规则?

C++ template specialization changes constexpr rules?

我正在使用 g++ (GCC) 11.2.0。

下面这段代码

#include <vector>
#include <iostream>

template<int size>
constexpr std::vector<int> get_vector() {
        return std::vector<int> (size);
}

int main() {
        std::cout << get_vector<5>().size() << std::endl;
}

编译成功,执行时输出5。正如我所料。

但是,如果我添加专业化

#include <vector>
#include <iostream>

template<int size>
constexpr std::vector<int> get_vector() {
        return std::vector<int> (size);
}

template<>
constexpr std::vector<int> get_vector<2>() {
        return std::vector<int> (2);
}

int main() {
        std::cout << get_vector<5>().size() << std::endl;
}

编译失败并产生错误

another.cpp: In function ‘constexpr std::vector<int> get_vector() [with int size = 2]’:
another.cpp:10:28: error: invalid return type ‘std::vector<int>’ of ‘constexpr’ function ‘constexpr std::vector<int> get_vector() [with int size = 2]’
   10 | constexpr std::vector<int> get_vector<2>() {
      |                            ^~~~~~~~~~~~~
In file included from /usr/include/c++/11.2.0/vector:67,
                 from another.cpp:1:
/usr/include/c++/11.2.0/bits/stl_vector.h:389:11: note: ‘std::vector<int>’ is not literal because:
  389 |     class vector : protected _Vector_base<_Tp, _Alloc>
      |           ^~~~~~
/usr/include/c++/11.2.0/bits/stl_vector.h:389:11: note:   ‘std::vector<int>’ has a non-trivial destructor

为什么会这样?

如果您查看 compiler support,您会发现 gcc 从版本 12 开始支持 constexpr std::vector。正如您告诉我们您使用的是 gcc 11.2,它根本没有在库中实现。

您可以在 godbolt 上使用 gcc 和 clang 的主干版本看到它按预期工作。对于 gcc,它将成为 gcc 12.x 版本的一部分。