非类型模板参数错误('x' 不是一种类型)

5

我正在尝试构建我的朋友的QT应用程序的OS X版本,他已经在Windows和Linux上构建了该应用程序。我们都使用g++,我正在使用gcc 4.2.1。不幸的是,我不知道他构建应用程序时使用的版本(那是相当长时间之前的事情)。

有人能解释一下为什么我会得到以下错误吗:

../../../src/dbapi/dbcore/node.h:24: error: 'dimensions' is not a type

当编译以下代码时:
Node.h:
template<class T,const unsigned int dimensions>
class EXPORT_DBCORE Node : public Transform<T,dimensions>
{
public:
  Node( Id id,
        QString& name,
        QString& text = "",
        // ************** Offending line: ***************
        Vector<T,dimensions> position = Vector<T,dimensions>(),
        Quaternion<T> rotation = Quaternion<T>() )
    : Transform<T,dimensions>( position, rotation )
    , mId( id )
    , mName( name )
    , mText( text )
  {
  }

private:
  ...
};

Vector.h:

template<class T,const unsigned int dimensions>
class EXPORT_DBCORE Vector
{
public:
  //! Default Constructor
  Vector()
  {
    mpArray = new T[dimensions];
    for( int i = 0; i < dimensions; i++ )
    {
      mpArray[i] = 0;
    }
  }
...

谢谢。

编辑:如果第24行不清楚,请参考Node.h节选中的“Offending line”注释。


1
你能提示我们代码片段中的第24行是哪一行吗? - Pete Becker
7
你是否在Node头文件中包含了Vector头文件?而且为什么要使用自己的向量类,既然Qt和标准库都有好用的类可以用? - Some programmer dude
4
你是否使用的是gcc 4.2.1编译器?如果你尝试使用较新版本的clang,或许会有更好的错误提示或者能够顺利运行。 - bames53
@PeteBecker 抱歉没有更清晰的说明。在我的Node.h摘录中,它用星号填充的注释表示。@JoachimPileborg 是的。我只是留下了很多文件。我没有编写这段代码,我不确定为什么要这样做。@bames53 是的,但我会尝试其他版本。知道问题的根源会很好,是有什么做错了还是只是编译器问题?@BoPersson 不确定,我尝试过没有“const”,但仍然得到相同的结果。 - Scott Stevenson
1
顺便提一下,我看到你在这里使用了QString,这通常意味着你正在使用QT。不要将模板与QT一起使用,它会破坏moc进程。 - Alex
@bames53,clang trunk因相同原因而拒绝它(请参见DR 325),GCC 4.4及更高版本接受它。 - Jonathan Wakely
1个回答

4

很不幸,我认为标准实际上认为这段代码是不规范的,请参见核心问题325。C++语法规定,默认参数的模板参数列表中的逗号被解析为下一个函数参数的开头,因此问题出在代码的= Vector<T, dimensions>()部分,所以dimensions被视为开始一个新的函数参数,而不是模板标识符的一部分。

GCC 4.4.0在近五年前进行了更改(请参见Bug 57),以接受这个代码,你有使用如此旧版本的好理由吗?

如果您无法升级,则可以通过向Node添加typedef 来解决该错误:

typedef Vector<T, dimensions> VectorType;

然后使用它:

  Node( Id id,
        QString& name,
        QString& text = "",
        VectorType position = VectorType(),
        Quaternion<T> rotation = Quaternion<T>() )

从技术上讲,只有默认参数需要使用typedef,但我会在参数声明和默认参数中使用它。实际上,我几乎总是为我的类使用的任何容器类型声明一个typedef,然后在类中使用该typedef。这通常比较短,并且意味着如果您更改容器,那么您通常只需要更新typedef,而不是每个使用它的地方。


非常好的解释,谢谢。我正在使用MacPorts 2.7版本,并且问题已经得到解决。我之前使用的是4.2.1版本,因为它是与Xcode捆绑在一起的。我认为与Xcode捆绑的版本对于OS X开发来说应该是最稳定的。 - Scott Stevenson
1
不,Xcode附带的是最后一个GPLv2许可的版本。苹果不会出售更新版本是因为许可证原因,而不是技术原因或稳定性原因。 - Jonathan Wakely

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接