G ++不喜欢模板方法链模板变种?(g++ doesn't like template me

2019-08-18 16:19发布

我试图使用g ++以前在Visual C ++ 2008 Express Edition的开发了一些代码编译,它看起来像G ++不会让我叫上一个模板变量的方法返回一个参考的模板方法。 我能够缩小问题到下面的代码:

class Inner
{
public:
  template<typename T>
  T get() const
  {
    return static_cast<T>(value_);
  };
private:
  int value_;
};

class Outer
{
public:
  Inner const& get_inner() { return inner_; };
private:
  Inner inner_;
};

template<typename T>
int do_outer(T& val)
{
  return val.get_inner().get<int>();
}

int main()
{
  Outer outer;
  do_outer(outer);
  return 0;
}

该代码在微软的编译器编译罚款,但G ++抛出一个错误:

$ g++ -c main.cpp
main.cpp: In function ‘int do_outer(T&)’:
main.cpp:24: error: expected primary-expression before ‘int’
main.cpp:24: error: expected ‘;’ before ‘int’
main.cpp:24: error: expected unqualified-id before ‘>’ token

其中线24是指return val.get_inner().get<int>();

如果我让do_outer常规方法接收Outer参考所述代码编译。 使Inner::get()正常的方法也适用。 并使得Inner::get()返回void并接受一个模板参数也是可行的,因为下面的INT符变得不必要的,即:

class Inner
{
public:
  template<typename T>
  void get(T& val) const
  {
    val = static_cast<T>(value_);
  };
private:
  int value_;
};

...

template<typename T>
int do_outer(T& val)
{
  int i;
  val.get_inner().get(i);
  return i;
}

...

(克++不complaing关于上面的代码)。

现在我的想法。 有什么问题? 有没有用gcc / g的问题++? 有没有我的代码合规问题?

我使用的编译器:

$ g++ --version
g++ (Ubuntu 4.3.3-5ubuntu4) 4.3.3

Answer 1:

你可以用试试?

template<typename T>
int do_outer(T& val)
{
  return val.get_inner().template get<int>();
}

我没有获得GCC个大气压,但我也有类似的问题,并添加模板关键字总是解决它们。 它工作在VS了。



Answer 2:

为了给上为什么一些背景template需要关键字:

template<typename T>
int do_outer(T& val)
{
  int i;
  val.get_inner().get<int>(i);
  return i;
}

当编译器看到这个功能,它不知道什么类型val是。 因此,它解析线val.get_inner().get(i)如下:

1: val .

编译器看到. 所以可以假设,“VAL”具有类类型和下一标识符是一个成员对象或功能的名称。

2. val . get_inner ( val . get_inner (

get_inner是该部件的名称,然后编译器看到( ,唯一的可能性是get_inner是函数名,因此这是一个函数调用。然后它解析参数,直到它找到的闭合)

3. val . get_inner () . val . get_inner () .

作为第一步骤,它现在知道因此它知道下一个标识符是一个成员对象或函数从get_inner返回必须是类的类型。

4. val . get_inner () . get < val . get_inner () . get <

所以,你可以在<可能是什么意思? 当然,它的模板参数开始...也许它的不到运营商?

我们知道, get只能是一个对象或一个函数。 如果它是一个对象,则<非常有意义作为除操作者的较少。 此外,只有其中名称之前,标准的更多或更少的状态<是一个template-name将它处理<作为模板参数(14.2 / 3):

后名称查找(3.4)发现,一个名字是一个模板的名称,如果该名称后面是<中, <总是被作为模板参数列表的开始,从来没有像其次less-名称不是运营商。

在这种情况下,编译器不知道该表达式的类型是什么val.get_inner()是,所以它无法查找get 。 它或多或少地假定,然后它的一个成员对象,而不是一个模板名称。 “<”被当作小于操作者和编译器结束了检查,如果get小于int -因此错误。

那么,为什么修复工作?

添加template关键字

从字面上我们告诉编译器的get是一个模板的名称,所以<操作被视为一个模板参数列表的开始。

拆除模板参数

当do_outer没有模板参数,即: val . get_inner () . get ( val . get_inner () . get ( val . get_inner () . get (编译器期望该成员get是一个对象或功能的(这两个名字被视为功能之间消歧。再后来模板参数推导出来的作品模板参数的类型。



Answer 3:

我不能自称是一个哦10人在这个星球谁完全理解C ++模板,但你在这里所做的看起来好像没什么问题。 (它失败,GCC 4.4.1同样的错误,BTW)。

更改do_outer

const Inner& inner = val.get_inner();
return inner.get<int>();

与海湾合作委员会的工作,想必也将使用Visual C ++工作。

你可能会考虑向海湾合作委员会的错误; 要么他们会解决它,否则将被关闭为无效,并在这个过程中会有人希望解释为什么你在做什么是无效的代码。

进一步的更新和AHA:原来它不是真正有效的代码,GCC只是给出了一个可怕的错误消息。 英特尔C ++输出(实际上是有帮助的!)错误信息:

template.cpp(24): error: type name is not allowed
    return val.get_inner().get<int>();

这让我意识到这个问题。 更改do_inner到

  return val.get_inner().template get<int>();

该代码由两个ICC和GCC接受。



文章来源: g++ doesn't like template method chaining on template var?