具有可变模板参数的临时对象; g ++/clang ++的另一个区别 [英] temporary objects with variadic template arguments; another g++/clang++ difference

查看:124
本文介绍了具有可变模板参数的临时对象; g ++/clang ++的另一个区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码

struct foo
 {
   foo ()
    { }

   template <typename T0, typename ... Ts>
      foo (const T0 & t0, const Ts & ... ts) 
       { foo(ts...); }
 };

int main()
 {
   foo f(1, 2);

   return 0;
 }

使用g++(4.9.2)编译时没有问题,并给出以下错误消息

compile without problems with g++ (4.9.2) and give the following errors

tmp_002-11,14,gcc,clang.cpp:9:16: error: expected ')'
       { foo(ts...); }
               ^
tmp_002-11,14,gcc,clang.cpp:9:13: note: to match this '('
       { foo(ts...); }
            ^
tmp_002-11,14,gcc,clang.cpp:9:14: error: redefinition of 'ts'
           { foo(ts...); }
             ^
tmp_002-11,14,gcc,clang.cpp:8:42: note: previous definition is here
      foo (const T0 & t0, const Ts & ... ts) 
                                         ^
2 errors generated.

clang++(3.5).

像往常一样,我的问题是:谁是对的?

As usual my question is: who's right?

---编辑---

澄清:我知道foo(ts...)不能是对委托构造函数的调用,但是(我认为可以)是构造临时foo对象(另一个foo对象)的方法.

Clarification: I know that foo(ts...) can't be a call to a delegate constructor but (I think that can be) the construction of a temporary foo object (another foo object).

但是,正如vsoftco指出的那样,sizeof...(ts) == 1U时会发生什么?

But, as pointed by vsoftco, what's happening when sizeof...(ts) == 1U?

在这种情况下,foo(ts...);是单个变量ts的(重新)声明(因此,我想应该是正确的clang++),否则可变参数语法可以避免此问题(因此,我想应该是正确的g++)吗?

In that case, foo(ts...); is a (re)declaration of a single variable ts (so, I suppose, should be right clang++) or the variadic syntax avoid this problem (so, I suppose, should be right g++)?

有C ++ 11标准专家可以澄清这一点吗?

There are C++11 standard experts that can clarify this?

p.s .:对不起,我的英语不好.

p.s.: sorry for my bad English.

推荐答案

这看起来像是一个lang虫.这是最小的复制品:

This looks like a clang bug. Here's a minimal reproduction:

template <typename ... Ts> void foo (Ts ... ts)
{
    int(ts...);
}

(甚至不需要实例化模板).

(there's no even need to instantiate the template).

从错误消息中判断,clang将int(ts...);解释为声明,但不能,因为(ts...)不能是声明器.

Judging from the error messages, clang interprets int(ts...); as a declaration, which it cannot be, because (ts...) cannot be a declarator.

一个人可能会问:当ts ...是一个大小为1的参数包时,是否应该不像ts那样对其进行解析,从而导致将整个构造解释为声明?答案是否定的.

One could ask: when ts... is a parameter pack of size one, shouldn't it be parsed similarly to ts and thus cause the whole construct to be interpreted as a declaration? The answer is no.

在C ++语法中,声明"和表达式声明"产生之间存在句法歧义.如果一个模棱两可的构造可以被解析为一个声明",那它就是一个声明". int(ts...)不能这样解析,因为语法没有这种解析所需的产生式.一旦构造被分类为表达式语句,而不是在此之前,我们可以将ts...解释为参数包并计算sizeof ...(ts).如果该构造未归类为表达式,则sizeof ...(ts)根本没有意义,因为ts ...没有意义,因为这样的语法不能包含在声明中.

There is a syntactic ambiguity in the C++ grammar between "declaration" and "expression-statement" productions. If an ambiguous construct can be parsed as a "declaration", it is a "declaration". int(ts...) cannot be parsed such, because the grammar does not have productions needed for such parse. Once the construct is classified as an expression statement, and not before that, we can interpret ts... as a parameter pack and calculate sizeof...(ts). If the construct is not classified as an expression, sizeof...(ts) has no meaning at all, because ts... has no meaning, as such syntax cannot be in a declaration.

一旦确定int(ts...);是一个表达式语句而不是一个声明,就可以解释它并实例化相关模板并扩展参数包.在这一点上,现在基于sizeof...(ts) == 1断言它一直是声明是为时已晚.如果sizeof...(ts) == 1是声明(ts不会是参数包),则无法推断出来.

Once it is established that int(ts...); is an expression statement and not a declaration, one may interpret it and instantiate relevant templates and expand parameter packs. At this point it's too late to go back and claim that it was a declaration all along, based on the fact that sizeof...(ts) == 1. One could not possibly deduce that sizeof...(ts) == 1 if it was a declaration (ts wouldn't be a parameter pack then).

此外,c似乎暗示它甚至不是语法上正确的声明.人们不可能从语法上不正确的东西中得出诸如sizeof...(ts) == 1之类的事实.

Moreover, clang seemingly insinuates that it is not even a syntactically correct declaration. One cannot possibly derive facts like sizeof...(ts) == 1 out of something that is not syntactically correct.

这篇关于具有可变模板参数的临时对象; g ++/clang ++的另一个区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆