Reputation: 967
I had the (bad) surprise to discover that the following code does not compile using CGG 5 or below, although it works like a charm with clang 4 or CGG 6 (and higher).
I don't really see what's going wrong, and what it shadowing template parameters of class B
. More importantly I don't see how I should tweak it so that it compiles with older versions of GCC...
#include <array>
template <typename T, int N>
struct A {
public:
std::array<T, 3> coordinates = { };
};
template <typename T, int N>
class B {
public:
A<T, N> *myA = new A<T, N>();
};
Compiler outputs:
<source>:12:29: error: expected ';' at end of member declaration
A<T, N> *myA = new A<T, N>();
^
<source>:12:29: error: declaration of 'A<T, N> B<T, N>::N'
<source>:9:23: error: shadows template parm 'int N'
template <typename T, int N>
^
<source>:12:30: error: expected unqualified-id before '>' token
A<T, N> *myA = new A<T, N>();
^
<source>:12:26: error: wrong number of template arguments (1, should be 2)
A<T, N> *myA = new A<T, N>();
^
<source>:4:8: error: provided for 'template<class T, int N> struct A'
struct A {
^
Compiler exited with result code 1
Upvotes: 1
Views: 370
Reputation: 7463
This is a GCC5 bug. You can work around it in various ways. The simplest is probably to add parentheses around the new expression, as pointed out in the comments:
template <typename T, int N>
class B {
public:
A<T, N> *myA = (new A<T, N> ());
};
Another way, perhaps a good idea on its own if you use the type a lot, would be to add using a_type = A<T, N>;
to the class, and then saying new a_type
:
template <typename T, int N>
class B {
private:
using a_type = A<T, N>;
public:
A<T, N> *myA = new a_type();
};
Although it doesn’t seem to be necessary, I added a main
function to ensure template instantiation just in case that affected the bug:
int main() {
B<int, 5> b1, b2;
b1.myA->coordinates = {{1, 2, 3}};
return b2.myA->coordinates.size();
}
Additionally, I assume these are just artifacts of making a minimal example, but just in case, a few additional points:
class B
has a memory leak: it never delete
s the pointers it new
s.class B
is an unnecessary level of indirection and the A
(or just the std::array
) should be a direct member.Upvotes: 2
Reputation: 604
You should initialize your pointer in a constructor, not in-class. Like so:
template<typename T, int N>
class B {
public:
B() : myA(new A<T, N>()) {}
~B() { delete myA; }
A<T, N> *myA;
};
Or, you could simply ditch the pointer:
template<typename T, int N>
class B {
public:
A<T, N> myA;
};
If you plan on using the pointer version, keep in mind that there are better ways to do this (std::unique_ptr
).
Upvotes: 1