Reputation: 223
I am trying to implement in a C++ class a constexpr member function which returns a template parameter. The code is supposed to be c++11 compatible. However I encounter compilation issues when the templated class also contains STL containers as data members such as std::vector (which are untouched by the constexpr member function).
A minimal example is given by the following code:
#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;
}
The code compiles correctly with the commands
g++ -std=c++14 -O3 quickTest.cpp -o test -Wall
clang++ -std=c++11 -O3 quickTest.cpp -o test -Wall
but fails when I use
g++ -std=c++11 -O3 quickTest.cpp -o test -Wall
with the error:
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’
Why does the code not compile with gcc -std=c++11
but does compile with clang++ -std=c++11
?
How could one make this code snippet work with older versions of gcc which may not support c++14/17, but only c++11?
I am using gcc 8.1.1 and clang 6.0.1
Upvotes: 22
Views: 1374
Reputation: 85382
C++11 had a rule [dcl.constexpr]/8:
... The class of which that function is a member shall be a literal type ([basic.types]).
struct A
is not a literal type because of the vector
, hence its non-static member functions cannot be constexpr
.
So GCC is right to reject the code in C++11 mode.
C++14 removed that restriction.
The solution for C++11 is to declare dimensions()
static
:
static constexpr size_t dimensions()
{
return n;
}
Upvotes: 20