【问题标题】:GCC error when compiling MS VC++ code with templates使用模板编译 MS VC++ 代码时出现 GCC 错误
【发布时间】:2011-02-11 14:00:57
【问题描述】:

我们正在获取一些为 Visual Studio 2008 编写的代码,并尝试使用 gcc 对其进行编译。我们在以下代码中遇到错误(简化为必要的):

template<int R, int C, typename T>
struct Vector
{
 template <typename TRes>
 TRes magnitude() const
 {
  return 0;
 }

};

struct A
{
 typedef Vector<3,1,int> NodeVector;
};

template<class T>
struct B
{
 void foo()
 {
  typename T::NodeVector x;
  x.magnitude<double>(); //< error here
 }
};

...
    B<A> test;
    test.foo();

GCC 说

error: expected primary-expression before 'double'
error: expected `;' before 'double'

你能解释一下这个错误吗?什么是交叉编译器解决方案?

非常感谢!

【问题讨论】:

标签: c++ templates gcc


【解决方案1】:

问题在于,由于 C++ 编译器不知道 T 的实际类型(更不用说 T::NodeVector 它不知道 magnitude 应该是一个模板。您需要明确指定:

x.template magnitude<double>();

否则 C++ 会将标记解析为xoperator.magnitudeoperator&lt;doubleoperator&gt;……

顺便说一句,GCC 是对的。 MSVC++ 在这些问题上是出了名的松懈。

【讨论】:

  • 如果没有歧义,松懈不一定是坏事(因为这里没有)。
  • @Blindy 如果它使您的代码在不同的编译器上中断。此外,您并不完全正确,由于模板专业化,这里存在 歧义(假设是传统的解析器),这就是这里需要 typenametemplate 的原因。正确解析它实际上非常非常困难,而且效率可能非常低。这个限制听起来很愚蠢,但实际上很有意义。
  • @Konrad,我认为没有其他方法可以解析流,因为最后一个 &gt; 在函数调用/成员变量访问/类名句柄中没有操作数。除了供应商特定的扩展总是会跨越编译器,想想__declspec 等等。它们仍然是无价的和不可替代的。
  • @Blindy 这就是为什么我说“假设一个传统的解析器”——解析器看不到 double 后面的标记,这需要任意前瞻(好吧,在这种情况下是 2,但它可能是大得多),这在传统的解析器中是禁止的。解析器必须在看到&lt; 时决定是将其视为运算符还是模板列表的开头。 MSVC++ 做了一些非常聪明的技巧来解析这个,但我敢打赌,在某个地方会有一个权衡。
  • @Blindy:它可以被解析为对函数模板实例的调用,(x.f&lt;3&gt;)(4),或者作为涉及两个比较运算符的表达式,(x.f &lt; 3) &gt; (4)。在不知道x.f是函数模板还是值的情况下,两者都有效,所以表达式是不明确的。
【解决方案2】:

在 B 点,它无法知道 x 是什么类型,而那个量级将是一个模板函数,所以你需要先将它声明为一个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多