-1

This might be a question with simple answer, but I tried every solution offered by google results, yet unable to fix this in VS 2017.I have a struct B with private destructor. I have another struct A that is friend of struct B, and trying to iterate through the vector of unique pointers to struct B. but I keep getting this error:

Severity Code Description Project File Line Suppression State Error C2248 'ProjectNamespace::NwSpec::~NwSpec': cannot access private member declared in class 'ProjectNamespace::NwSpec' TestProject c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\memory 2055

Any pointers will be greatly appreciated. Thanks.

        struct A
        {
        //functions
        std::vector<std::unique_ptr<NwSpec>> List;
        bool function()const;
        };

        struct NwSpec
        {
            char* Path;//Assume Path is initialized and set with a string.

            private:
                ~NwSpec();

            friend struct A;
        };

        bool A::function()const 
        {
            for (uint32_t i = 0 ; i < List.size(); i++)
            {

            OutputDebugStringA(List[i]->Path);// Error C2248
            }
            // I used iterator to the vector, but getting same error.
            // I used for(const auto& k : List) but getting same access error.
            // NwSpec is visible to A and within ProjectNamespace
        }
recnac
  • 3,744
  • 6
  • 24
  • 46
Swtsvn
  • 307
  • 1
  • 3
  • 12
  • What is `Path`? – NathanOliver Jul 31 '18 at 16:28
  • Path is char* Path – Swtsvn Jul 31 '18 at 16:30
  • What is `Struct`? –  Jul 31 '18 at 16:31
  • Fixed with "struct". sorry about that – Swtsvn Jul 31 '18 at 16:32
  • 1
    JUST STOP. Think about what you want to post and post the code. Six edits in two minutes is wasting everyone's time. – Pete Becker Jul 31 '18 at 16:32
  • Understood. Will not happen again. – Swtsvn Jul 31 '18 at 16:32
  • The provided code is incomplete, and does not compile as given. I added what I can only presume was the missing code, and it works on my machine. If you could provide a complete example which will compile, that will help to determine what is going awry. At the moment, I can only presume the bug is in the code not provided. – Eljay Jul 31 '18 at 16:38
  • `friend` is not transitive. – Richard Critten Jul 31 '18 at 16:39
  • 1
    What is the intended purpose of declaring the destructor for `NwSpec` to be private? `std::unique_ptr` won't be able to delete it if it can't access it, which is the root cause of your error. If the decision was arbitrary, I'll post this as an answer, but I suspect this is an [XY-Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) where the decision to make the destructor private in the first place is much closer to the root problem. – Xirema Jul 31 '18 at 16:45
  • Eljay, I created a new project with just the necessary code like you mentioned, and it is compiling successfully for me too. I am thinking the issue is somewhere else in the big project that this code is a part of. – Swtsvn Jul 31 '18 at 17:03
  • Xirema, This code is part of a huge project, which can be loaded by another project as dll and accessed. Hence keeping the destructor private. struct A is a friend of struct NwSpec, hence should be able to access its destructor, but no other class/function/struct should be able to delete the memory of the NwSpec. hence the design choice. – Swtsvn Jul 31 '18 at 17:05

1 Answers1

1

You need to create a specialized type responsible for the deletion of the NwSpec object, and provide that to the std::unique_ptr:

struct NwSpec;

struct A {
private:
    struct NwSpecDeleter {
        //Note that we're only declaring the function, and not defining it
        void operator()(NwSpec * ptr) const;
    };
public:
    typedef std::unique_ptr<NwSpec, NwSpecDeleter> ptr_type;
    std::vector<ptr_type> List;
    bool function()const;
};

struct NwSpec {
    char* Path;//Assume Path is initialized and set with a string.

private:
    ~NwSpec();

    friend struct A;
};

NwSpec::~NwSpec() {}

void A::NwSpecDeleter::operator()(NwSpec * ptr) const {
    delete ptr;
}

int main() {
    A a;
    a.List.emplace_back(new NwSpec());
    auto ptr = a.List.back().release();
    //This will not compile, as intended
    //delete ptr;
    //Nor will this:
    //ptr->~NwSpec();
    //But this will compile, because the original unique_ptr is perfectly capable of deleting objects:
    a.List.back().reset(ptr);
    a.List.back().reset();//Object is successfully deleted

    a.List.erase(a.List.begin(), a.List.end());
    a.List.emplace_back(new NwSpec());
    //This also compiles
    a.List.erase(a.List.begin(), a.List.end());
    return 0;
}

This code can be tested here.

Xirema
  • 19,889
  • 4
  • 32
  • 68