将括号添加到构造函数调用会导致xl c C ++编译器中出现重复参数错误

时间:2013-01-18 17:05:51

标签: c++ parameters constructor parentheses xlc

我们正在创建一种特定于域的语言,该语言生成必须在gcc下编译的C ++代码以及IBM xlc(适用于AIX的10.1版)编译器。

一个特定的代码片段生成的C ++代码在gcc下运行得非常好,但在xlc下没有那么多。我已将代码修改为仍然触发编译错误的最小情况:

//bug183.h
class emptyList
{};

extern emptyList weco;

class otherClass
{
        public:
                otherClass();
                otherClass(const int & p);
                otherClass(const emptyList & e);
                int geta() {return a;}
        private:
                int a;
};

class someClass
{
        public:
                someClass();
                someClass(const someClass & other);
                someClass(const otherClass & p1, const otherClass & p2);
                void exportState();

        private:
                otherClass oc1;
                otherClass oc2;

};

//bug183.cpp
#include "bug183.h"
#include <iostream>

emptyList weco = emptyList();

otherClass::otherClass() {a = 0;}
otherClass::otherClass(const int & p) {a = p;}
otherClass::otherClass(const emptyList & e) {a = 1000;}

someClass::someClass() {oc1 = otherClass(); oc2 = otherClass();}
someClass::someClass(const someClass & other) {oc1 = other.oc1; oc2 = other.oc2;}
someClass::someClass(const otherClass & p1, const otherClass & p2) {oc1 = p1; oc2 = p2;}
void someClass::exportState() {std::cout << oc1.geta() << " " << oc2.geta() << std::endl;}

int main()
{
        someClass dudi;
        dudi.exportState();

        //this line triggers the error in xlc
        someClass nuni = (someClass(otherClass(weco), otherClass(weco)));
        nuni.exportState();

        return 0;
}

编译它会导致引发以下错误: “bug183.cpp”,第21.66行:1540-0114(S)参数名称不能与此函数的另一个参数相同。

但是如果我删除构造函数调用中的括号括起来:

someClass nuni = someClass(otherClass(weco), otherClass(weco));

错误消失了。此外,如果我将weco更改为另一个创建为weco的外部变量,即使我将构造函数括在括号中,错误也会消失,因此可以肯定地说这两个条件都需要存在出现错误。

有些人可能会问为什么我们不删除括号,但这样做可能会损害部分正常工作的代码,所以我倾向于理解这种行为是否正确是否可以从C ++编译器开始,或者至少有一个已知的解决方法。

1 个答案:

答案 0 :(得分:2)

我认为

(someClass(otherClass(weco), otherClass(weco)))

被错误地解析为 cast-expression 的第二次制作的开始:

  

铸表达:   
一元表达式   
( type-id ) cast-expression

注意§8.2第2段(重点补充):

  

函数式转换和 type-id 之间的相似性引起的歧义可能发生在不同的上下文中。歧义似乎是函数式转换表达式和类型声明之间的选择。解决方案是在其语法上下文中可能是 type-id 的任何构造都应被视为 type-id

如果您考虑 cast-expression type-id 的完整语法上下文,...中的(..);不可能匹配type-id,因为)后面的 cast-expression 不能为空。但是,如果您只考虑one-token-lookahead上下文,其中 type-id 必须跟),则8.2(2)适用可能是合理的。我并不是真的倾向于认为标准的意图只是考虑一个令牌前瞻。

修改 报告为gcc bug 50637。您可能希望向xlc提交类似的错误报告。

因为gcc 4.7.2似乎标记了与xlc相同的错误。我玩了一下gcc,并说服自己问题是gcc标记了 type-id 中的错误(即两个具有相同名称的参数),然后才发现括号表达式不能是 type-id

以下是一个例子:

#include <iostream>
#include <utility>

static const int zero = 0;
int main() {
  // Consistent with 8.2[2]
  // Example 1. Invalid cast.
  // Here, 'int(int(zero))' is a type-id, so the compiler must take
  // the expression to be a cast of '+3' to a function.
  std::cout << (int(int(zero))) + 3 << std::endl;
  // Example 2: No error.
  // The parenthesized expression cannot be a type-id in this context
  std::cout << (int(int(zero))) << std::endl;
  // Example 3: Syntax error: zero redefined.
  // Here the parenthesized expression could be a type-id, so it must
  // be parsed as one, even though the type-id is invalid.
  std::cout << (std::pair<int,int>(int(zero), int(zero))) + 3 << std::endl;

  // Apparently not consistent with 8.2[2]
  // Here the parenthesized expression can't be a type-id, as in example 2.
  // However, the type-id triggers a syntax error, presumably before gcc
  // figures out that it's not a cast-expression.
  std::cout << (std::pair<int,int>(int(zero), int(zero))) << std::endl;

  return 0;
}

on lws。 (在gcc和clang之间切换以查看差异。)

基于上述分析,问题是过早触发类型错误,这是一个可能的解决方法:

1)为weco添加别名:

emptyList& weco_alias = weco;

2)使用其中一个:

someClass nuni = (someClass(otherClass(weco), otherClass(weco_alias)));

这适用于gcc 4.7.2和clang 3.2(lws)。