Search code examples
c++variadic-templatesusingfriend-class

How to declare a template friend class inside other template class?


  • Hello. I'm trying to implement double linked list. I have a linked_list class and DListNode class as a shell for elements in my container and I prefer DListNode as a class rather than as a struct, because I want node fields to be inaccessible outside, but I also need to get an access to them in a linked_list class, so instead of making getters and setters I have chosen to make linked_list as a friend class for DLinstNode to improve encapsulation.

  • Problem: I did what I planned like this:

template <
    class Dty_
>
class DListNode {
public:

// ...

template <class ...> friend class linked_list; // line 168
// template <class ...> friend class linked_list<Dty_, DListNode<Dty_>, std::allocator<Dty_>>; full specialization doesn't work too

protected:
// ...
};



template <
    class Ty_,
    template <class ...> class List_node_ = DListNode,
    class Alloc_ = std::allocator<Ty_>
>
class linked_list { // line 13

// ...

};
  • And got an error in line 13: "redeclared with 3 template parameters"

  • The full error text:

C:\Users\averu\github-local\base\ds\list\list.cpp:13:7: error: redeclared with 3 template parameters
   13 | class linked_list { // biderectional double linked list
      |       ^~~~~~~~~~~
In file included from C:\Users\averu\github-local\base\ds\list\iterator.cpp:2,
                 from C:\Users\averu\github-local\base\ds\list\list.cpp:1:
C:\Users\averu\github-local\base\ds\list\node.cpp:168:39: note: previous declaration 'template<class ...> class linked_list' used 1 template parameter
  168 |     template <class ...> friend class linked_list;
      |     
  • Questions:
    1. How to declare what I planned in a right way?
    2. Is there any better way to do this?
    3. Any other recommendations?

As you can see there I'm trying to use variadic template, but it doesn't work. So, perhaps I need to declare class linked_list forward via using declaration how then do it?

full code there


Solution

  • You declaration of the friend class uses different template arguments than the definition of linked_list. You need to declare it as a friend like so:

    class DListNode {
    public:
        template <class, template <class...> class, class> friend class linked_list;
    };
    

    becaus linked_list has one class template argument, followed by a template template argument, followed by another class argument.

    https://godbolt.org/z/hxhP396nv