0

I'm trying to build a generic container class using templates so that I can store an arbitrary data type in the container. I have a generic interface class with a virtual "get" method that returns an object of the parametrized type. One common use of this container will be to create a "container-of-containers" with 2 or more levels. What I'd like to do is provide a recursive "get" method that will traverse the hierarchy and return an item from a leaf node.

Here is some example code showing what I'm trying to do:

#include <iostream>

template<typename DataT>
class container_intf
{
   public:

      container_intf() = default;
      virtual ~container_intf() = default;
      virtual DataT get() = 0;
};

class one : public container_intf<int>
{
   public:
      int get() { return 1; };
};

class two : public container_intf<int>
{
   public:
      int get() { return 2; };
};


template<typename DataT>
class generic : public container_intf<DataT>
{
   public:
      DataT get()
      {
         return DataT();
      };
};


int main(int argc, char** argv)
{
   one o;
   two t;
   std::cout << o.get() << "\n";
   std::cout << t.get() << "\n";


   generic<int> g;
   std::cout << g.get() << "\n";

   generic<one> one_nested;
   std::cout << one_nested.get().get() << "\n";


   generic< generic<two> > two_nested;
   std::cout << two_nested.get().get().get() << "\n";

   return 0;
};

Basically, I'd like to be able to call "two_nested.get()" instead of "two_nested.get().get().get()". I've tried using type traits and std::enable_if but I haven't been able to get it to work. A helper class or function would be fine; I just want to be able to support a hierarchy of arbitrary depth.

Stephan
  • 1,007
  • 7
  • 9
  • If the container didn't define `get()` at all, and only the base case defined `get()`, then calling `two_nested.get()` would go all the way to the base case directly. – VoidStar May 22 '15 at 19:38

1 Answers1

0

Wouldn't return DataT().get() in the function generic<DataT>::DataT get() solve the issue?

I mean the following class definition:

template<typename DataT>
class generic : public container_intf<DataT>
{
   public:
      //if using c++14, you can use just `auto` as a return type
      decltype (DataT::get()) get() 
      {
         return DataT().get(); //< instead of just `return DataT();`
      };
};
gluk47
  • 1,812
  • 20
  • 31
  • That won't work when DataT = int. Further, the function needs to have the same signature as the virtual function "DataT get()" in container_intf. – Stephan May 22 '15 at 21:13
  • You are right, the function will become not virtual. Although, i'm not sure what exactly is the use-case of such virtual function in a templated class, it might happen that virtuality is redundant here (might not). If virtuality is not essentially needed, you can employ `std::enable_if` here, like explaned [there](http://stackoverflow.com/a/264088/1266605). – gluk47 May 23 '15 at 21:13
  • The virtual function is so that I can use polymorphism to provide different implementation of the container_intf type. It all works fine except for nested containers, which require the user to call "get().get()...". As mentioned in my original question, I tried enable_if and it didn't work for creating a recursive "get" method. – Stephan May 26 '15 at 18:18