使用GCC 5进行模板参数遮蔽

时间:2017-07-18 15:11:41

标签: c++ templates gcc

我发现下面的代码不能使用CGG 5或更低版本进行编译,这让我感到非常惊讶,尽管它的作用类似于clang 4或CGG 6(及更高版本)的魅力。

我真的不知道出了什么问题,以及它对类B的模板参数的影响。更重要的是,我不知道如何调整它以便它与旧版本的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>();
};

编译器输出:

<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

2 个答案:

答案 0 :(得分:2)

is a GCC5 bug。您可以通过各种方式解决它。最简单的可能是在新表达式周围添加括号,如in the comments所述:

template <typename T, int N>
class B {
public:
    A<T, N> *myA = (new A<T, N> ());
};

另一种方式,如果您经常使用该类型,可能是一个好主意,就是将using a_type = A<T, N>;添加到课程中,然后说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();
};

虽然似乎没有必要,但我添加了一个main函数来确保模板实例化,以防万一影响了这个bug:

int main() {
    B<int, 5> b1, b2;
    b1.myA->coordinates = {{1, 2, 3}};
    return b2.myA->coordinates.size();
}

此外,我认为这些只是制作一个最小例子的工件,但为了以防万一,还有一些额外的要点:

  • 您的class B内存泄漏:它永远不会delete指向它new
  • 根据编码风格,如果构造函数具有复杂的初始化,则初始化变量可能更为惯用,除非它应该是静态的。
  • 根据您向我们展示的内容,class B中的指针是不必要的间接级别,A(或仅std::array)应该是直接成员。

答案 1 :(得分:1)

您应该在构造函数中初始化指针,而不是在类中。像这样:

template<typename T, int N>
class B {
public:
    B() : myA(new A<T, N>()) {}
    ~B() { delete myA; }
    A<T, N> *myA;
};

或者,你可以简单地抛弃指针:

template<typename T, int N>
class B {
public:
    A<T, N> myA;
};

如果您打算使用指针版本,请记住有更好的方法(std::unique_ptr)。