Friend, private function, template alias, and decltype… is clang correct in rejecting this?

こ雲淡風輕ζ 提交于 2021-02-07 06:55:25

问题


In the following code (godbolt link):

#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 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.

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

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

Note: gcc 7.x, 8.x, and 9.x accept the code.


回答1:


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.

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.

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;


来源:https://stackoverflow.com/questions/61410959/friend-private-function-template-alias-and-decltype-is-clang-correct-in-re

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!