朋友,私有函数,模板别名和decltype ...用clang拒绝是正确的吗? [英] Friend, private function, template alias, and decltype... is clang correct in rejecting this?

查看:62
本文介绍了朋友,私有函数,模板别名和decltype ...用clang拒绝是正确的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下代码中( godbolt链接):

#include <utility>

struct Friend {
    class Inner {
        friend struct Friend;

        int function() { return 0; }
    };

    using DirectResult = decltype(std::declval<Inner>().function());

    template <typename T>
    using IndirectResult = decltype(std::declval<T>().function());
};

int main() {
    Friend::DirectResult direct{};
    Friend::IndirectResult<Friend::Inner> indirect{};
    return direct + indirect;
}

Clang对使用 DirectResult 感到非常满意,但是会抱怨 IndirectResult 试图访问 private 函数内部:

Clang is perfectly happy with the use of DirectResult, but will complaing that IndirectResult is attempting to access a private function of Inner:

<source>:13:55: error: 'function' is a private member of 'Friend::Inner'    
    using IndirectResult = decltype(std::declval<T>().function());
                                                      ^
<source>:18:13: note: in instantiation of template type alias 'IndirectResult' requested here
    Friend::IndirectResult<Friend::Inner> indirect{};
            ^

由于模板别名是在好友类中声明的,因此我希望可以很好地进行访问.

I would have expected the access to be fine, as the template alias is declared within the friend class.

但是,以我的经验,在解释C ++标准时,Clang通常是正确的(比gcc更重要).

However, in my experience Clang is generally right (more so than gcc) when it comes to interpreting the C++ standard.

Clang拒绝此代码是否正确?如果是,我还缺少什么?

Is Clang correct in rejecting this code? And if so, what am I missing?

注意:gcc 7.x,8.x和9.x接受代码.

推荐答案

这是 abug .每个 [class.friend]/2 :

This is a bug in Clang. Per [class.friend]/2:

将一个类声明为朋友意味着可以从该类的基础说明符和成员声明中访问该类授予友谊的私有成员和受保护成员的名称.

Declaring a class to be a friend implies that the names of private and protected members from the class granting friendship can be accessed in the base-specifiers and member declarations of the befriended class.

每个> [class.mem] 模板声明可以是成员声明,并且每个

Per [class.mem], a template-declaration can be a member-declaration, and per [temp.pre]/2.5 an alias-declaration can be the declaration in a template-declaration. So a member alias template has access to the private and protected members of the class's friends.

幸运的是,该错误似乎仅适用于 alias-declaration defining-type-id ;您可以通过将计算移到帮助程序类(具有嵌套的 type 别名)中或更简单地将其移至默认模板参数 来解决此问题:

Fortunately, the bug appears only to apply to the defining-type-id of an alias-declaration; you can work around it by moving the computation into a helper class (with nested type alias), or more concisely to a default template-argument:

template <typename T, class U = decltype(std::declval<T>().function())>
using IndirectResult = U;

这篇关于朋友,私有函数,模板别名和decltype ...用clang拒绝是正确的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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