Lambdas,本地类型和全局命名空间 [英] Lambdas, local types, and global namespace

查看:190
本文介绍了Lambdas,本地类型和全局命名空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此最小程序

template <typename X>
void foo (X x)
{
    bar (x);
}

template <typename X>
void bar (X x)
{
}

int main ()
{
    foo ([]{});
}

使用gcc(4.8.5和5.3)编译并且无法使用clang (3.7)

compiles with gcc (4.8.5 and 5.3) and fails to compile with clang (3.7)

我的分析如下。

bar foo 中使用,并在 foo 后声明,因此在 foo 定义点。在 foo 实例化点可以通过参数相关查找找到 bar 的唯一方法。

bar is used in foo and declared after foo, so it is not visible at foo definition point. The only way bar can be found at foo instantiation point is via argument-dependent lookup.

foo bar 的唯一参数是一个在 main 中定义的lambda。

The only argument to both foo and bar is a lambda defined in main.

显然gcc认为它的类型是在全局命名空间中声明的,而clang 。因此,gcc可以通过ADL和clang找到 bar

Apparently gcc regards its type as declared in the global namespace, while clang does not. Thus, gcc can find bar via ADL and clang cannot.

当我们使用本地定义的类型在

Same thing happens when we use a type defined locally in main:

int main ()
{
    struct K{};
    foo (K());     // gcc compiles, clang complains
}

看起来gcc在这里出错。根据标准的lambda的类型是未命名(expr.prim.lambda / 3),因此它不应属于任何命名空间。本地类型应该不属于全局命名空间。

It looks like gcc is in the wrong here. The type of the lambda according to the standard is unnamed (expr.prim.lambda/3), so it should not belong to any namespace. The local type supposedly shouldn't belong to the global namespace either.

分析是否正确?这是一个已知的gcc错误?

Is the analysis correct? Is this a known gcc bug?

这个问题的灵感来自

This question is inspired by this question.

推荐答案

GCC是正确的,每个 DR1690 / 1691 的解决方案。

GCC is correct, per the resolution of DR1690/1691.

[expr.prim.lambda] / 4


闭包类型是在最小的块范围,类范围,
或包含相应的lambda表达式的命名空间范围中声明的 。
[注意:这决定了关联类型([basic.lookup.argdep])的关联
的命名空间和类的集合。
a <> lambda-declarator 的参数类型不会影响这些关联的命名空间和
类。 - 结束注释]

The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression. [ Note: This determines the set of namespaces and classes associated with the closure type ([basic.lookup.argdep]). The parameter types of a lambda-declarator do not affect these associated namespaces and classes. — end note ]

[basic.lookup.argdep] / 2


如果 T 是类类型(包括联合),它的关联类是:
类本身;它是其成员的类,如果有的话;和
直接和间接基类。它相关的命名空间是
其相关类的最内层命名空间。

If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a member, if any; and its direct and indirect base classes. Its associated namespaces are the innermost enclosing namespaces of its associated classes.

封闭类型的最内层命名空间是全局命名空间,因此全局命名空间是一个关联的命名空间。

The innermost enclosing namespace of the closure type at issue is the global namespace, so the global namespace is an associated namespace.

这篇关于Lambdas,本地类型和全局命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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