我正在尝试在C ++类中实现constexpr成员函数,该成员函数返回模板参数。该代码应该与c ++ 11兼容。但是,当模板化类还包含STL容器作为数据成员(如std :: vector)时,会遇到编译问题(constexpr成员函数未涉及到这些容器)。
以下代码给出了一个最小的示例:
#include <vector>
#include <iostream>
#include <array>
template<size_t n>
struct A
{
constexpr size_t dimensions() const
{
return n;
}
private:
std::vector<double> a;
};
int main(int argc,char ** argv)
{
auto a=A<3>();
std::array<double,a.dimensions()> arr;
}
代码可以使用命令正确编译
g ++ -std = c ++ 14 -O3 quickTest.cpp -o test -Wall
clang ++ -std = c ++ 11 -O3 quickTest.cpp -o test -Wall
但使用时失败
g ++ -std = c ++ 11 -O3 quickTest.cpp -o test -Wall
有错误
quickTest.cpp:22:33: error: call to non-‘constexpr’ function ‘size_t A<n>::dimensions() const [with long unsigned int n = 3; size_t = long unsigned int]’
std::array<double,a.dimensions()> arr;
~~~~~~~~~~~~^~
quickTest.cpp:10:20: note: ‘size_t A<n>::dimensions() const [with long unsigned int n = 3; size_t = long unsigned int]’ is not usable as a ‘constexpr’ function because:
constexpr size_t dimensions() const
^~~~~~~~~~
quickTest.cpp:22:33: error: call to non-‘constexpr’ function ‘size_t A<n>::dimensions() const [with long unsigned int n = 3; size_t = long unsigned int]’
std::array<double,a.dimensions()> arr;
~~~~~~~~~~~~^~
quickTest.cpp:22:33: note: in template argument for type ‘long unsigned int’
为什么代码不能用gcc -std=c++11
编译,而不能用clang++ -std=c++11
编译?
如何使此代码段与旧版本的gcc一起使用,而许多旧版本的gcc不支持c ++ 14/17,而仅支持c ++ 11?
我正在使用gcc 8.1.1和clang 6.0.1
答案 0 :(得分:20)
C ++ 11的规则为[dcl.constexpr]/8:
由于...该函数所属的类应为 文字类型 ([basic.types])。
struct A
, vector
不是文字类型,因此其非静态成员函数不能为constexpr
。
所以GCC在C ++ 11模式下拒绝代码是正确的。
C ++ 14 removed的限制。
C ++ 11的解决方案是声明dimensions()
static
:
static constexpr size_t dimensions()
{
return n;
}