Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

class wrapper { private:     template <typename T>     class __tklass {};      class __klass {}; };  template <typename T> using tklass = wrapper::__tklass<T>;    // Expected error but compiles OK  // using klass = wrapper::__klass;      // "Error: __klass is private"  int main() {     tklass<int> v1;                     // Expected error but compiles OK      // wrapper::__tklass<int> v3;       // "Error: __tklass is private"     // wrapper::__klass v4;             // "Error: __klass is private" } 

The lines marked "Error: __xxx is private" correctly report an error when uncommented. But the lines with tklass get compiled without any complaint from the compiler.

So why exactly doesn't the compiler flag tklass as error despite wrapper::__tklass being private? Is it by any chance allowed by the standard? If so, wouldn't that be considered a serious access violation?

I tried this on gcc-4.9.2, clang-3.5.0 and visual studio 2013 express. GCC command line:

g++ -std=c++11 -pedantic -Wall -Wextra -Wshadow myfile.cpp 
like image 310
nav Avatar asked Jan 15 '15 09:01

nav


People also ask

Can private member of class be access outside the class?

Private: The class members declared as private can be accessed only by the functions inside the class. They are not allowed to be accessed directly by any object or function outside the class. Only the member functions or the friend functions are allowed to access the private data members of a class.

Can we access private data members of a class without using a member or a friend function in C ++?

In C++, a friend function or friend class can also access private data members. So, is it possible to access private members outside a class without friend? Yes, it is possible using pointers.

How to call private member function of a class in c++ program?

Either make the function itself public or add another public function to call the private one: class cricket { private: // ... void cal_penalty_impl() { // Your original code goes here // ... } public: // ...


2 Answers

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.

like image 200
Barry Avatar answered Oct 14 '22 15:10

Barry


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

like image 30
3 revs Avatar answered Oct 14 '22 15:10

3 revs