3
votes

I have the following code:

#include <memory>

template<typename T, size_t Level>
class Foo
{
    friend class Foo<T, Level + 1>;
    typedef std::unique_ptr<T> ElmPtr;
    typedef std::unique_ptr<Foo<ElmPtr, Level - 1>> NodePtr;        

    public:
    Foo() {
        // no errors
        auto c = children;
    }

    Foo(int n) {
        // !!! compiler error !!!
        auto c = children;
    }

    std::array<NodePtr, 4> children;            
};

template<typename T>
class Foo<T, 0>
{
    friend class Foo<T, 1>;

    public:
    Foo() {}
};

int main()
{
    Foo<int, 1> foo1;
}

I get the following error:

error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'

Why? How can I fix this problem?

1
Both constructors give an error for me, and it's because you're trying to copy a std::unique_ptr, which is impossible. You have to either move from it or bind it to a reference. - 0x499602D2
You'll need to use auto c = std::move(children); in both places. And we can't tell you why it compiles in once place and not the other because you haven't provided an SSCCE. - Praetorian
@Praetorian: How is this not a SSCCE? It's short, it's compilable. Sadly it's missing the correct #include <...> lines, but this is far more than we normally get. - Bill Lynch
g++ 4.8..2 shows an error in the default constructor, too - user2249683
@Nick: The problem is that the code you provided doesn't give the errors you describe in any compiler I can find. Not clang, not GCC, and not MSVC even. The second C in SSCCE stands for "Correct" and one thing that means is "the example... causes the exact error message about which needs solving." sscce.org Without this, we'll end up solving the code here with a fix that doesn't help you at all. - Mooing Duck

1 Answers

5
votes

You have:

auto c = children;

Where:

std::array<std::unique_ptr<T>, N> children;            

That would require copying unique_ptrs, and unique_ptr is not copyable. You can take a reference to children though:

auto& c = children; // OK