3

Good morning everybody, I'm trying to write a member function of a class OUTER_CLASS which returns a unique_ptr to a private class INNER_CLASS defined within the OUTER_CLASS itself. My intent is to write a factory method which returns a reference to an Interface Class which allows to interact with the Implementation Class hided from client. Apart from the design choice, I have a compilation issue: given the following snippet of code, which is a very simplified version of my architecture


#include <iostream>
#include <string>
#include <vector>
#include <memory>

using namespace std;

class OuterClass
{
    class InnerClass
    {
        friend class OuterClass;        
        public:
            void myPrint() { cout << "Inner Class " << a << endl;}
            InnerClass(int inA) : a(inA) {};
        private:
            int a;
    };
public:
    std::unique_ptr<InnerClass> CreateInnerClass()
    {
        std::unique_ptr<InnerClass> innerObj;
        innerObj.reset(new InnerClass(1));
        return innerObj;
    }
};


int main()
{
    OuterClass obj;
    std::unique_ptr<OuterClass::InnerClass> innerObj = obj.CreateInnerClass();    
    innerObj->myPrint();
}

I get following error:

main.cpp: In function 'int main()':
main.cpp:43:10: error: 'class OuterClass::InnerClass' is private within this context
   43 |     std::unique_ptr<OuterClass::InnerClass> innerObj = obj.CreateInnerClass();
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:20:11: note: declared private here
   20 |     class InnerClass
      |           ^~~~~~~~~~

if instead i use AUTO type deduction, writing

int main()
{
    OuterClass obj;
    auto innerObj = obj.CreateInnerClass();    
    innerObj->myPrint();
}

everything is fine... How is it possible? What am i doing wrong? Thanks in advance for any answer

fabiop
  • 179
  • 10

1 Answers1

2

Accessibility applies on name, not the type being referred to. So you just can't use the name OuterClass::InnerClass directly in main(), but you can still use the type like calling member functions on the returned object whose type is OuterClass::InnerClass like

obj.CreateInnerClass()->myPrint();

Given auto innerObj = obj.CreateInnerClass(); the name OuterClass::InnerClass is not used directly then it doesn't violate the accessibility check. For the same reason you can use decltype too, even it seems redundant. E.g.

decltype(obj.CreateInnerClass()) innerObj = obj.CreateInnerClass(); 
songyuanyao
  • 169,198
  • 16
  • 310
  • 405