本文介绍了朋友,私有函数,模板别名和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:

每个> [class.mem] 模板声明可以是成员声明,并且每个 [temp.pre]/2.5 别名声明可以是模板声明.因此,成员别名模板可以访问该类朋友的私有成员和受保护成员.

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拒绝是正确的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 18:54