C++11: Why is private member template accessible outside class?

后端 未结 2 460
没有蜡笔的小新
没有蜡笔的小新 2020-12-29 02:49

I just happened to find that a nested private template class can be accessed directly outside the enclosing class using a using directive:

class         


        
相关标签:
2条回答
  • 2020-12-29 03:05

    Herb Sutter wrote long ago the article, how template member functions may provide a back-door into a class: http://www.gotw.ca/gotw/076.htm (pls. check the case 4: "The Language Lawyer", at the end)

    It may give you the answer.

    EDIT: I'm curious, what were the reasons for down-voting. I cite the article: "Is this a hole in C++'s access control mechanism, and therefore a hole in C++'s encapsulation? This demonstrates an interesting interaction between two C++ features: The access control model, and the template model. It turns out that member templates appear to implicitly "break encapsulation" in the sense that they effectively provide a portable way to bypass the class access control mechanism."

    Seems for me to be a reasonable answer. EDIT END

    One could spent plenty of time trying to secure the interfaces by technical means private/protected, etc. My preferred way is to make an agreement among all developers to use well, understood rules complying with least surprise approach. (EDIT: And verify the code against these rules using the code-reviews/reg-exp scripts on regular basis)

    "Don't try to find a technical solution for a social problem" B. Stroustrup

    0 讨论(0)
  • 2020-12-29 03:21

    This is definitely a compiler bug, and actually one that has been known for quite some time: GCC #47346 (first reported in Jan 2011) and Clang #15914 (first reported May 2013). Your __tklass is clearly private, and the template alias is not marked friend, so this should be a simple access error.

    The simplest reproduction is from the Clang example attachment, this version compiles on both gcc 4.9.2 and clang 3.5.0, though should definitely compile on neither:

    class A
    {
      class B {};
    };
    
    template<typename>
    using T = A::B;
    
    T<void> t;
    

    Clang is strictly better than GCC on this front however, as this particular bug seems to occur only with template aliases. A "workaround" (if you need such a thing for cases that the compiler allows incorrectly...) would be to revert back to pre-C++11 template aliasing:

    template <typename>
    struct T {
        using type = A::B;
    };
    
    T<void>::type t;
    

    That code correctly fails to compile with clang (error: 'B' is a private member of 'A'), but still compiles fine with gcc.

    0 讨论(0)
提交回复
热议问题