Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Policy Based Design with Variadic Templates

I have a set of homogeneous policy classes that I want to pass as policies to a template class, PolicyDrivenClass, which takes some unknown number of policy template parameters.

Each policy implements a "name" function, and I would like to be able to query the names of all of the policies at run time via PolicyDriveClass::getNames.

I have a working implementation, but it feels clunky, especially given that in my final design the Policy classes will implement several functions similar to "name", though perhaps with different return types, and that my Policy Driven Class will want to provide accessors similar to "getNames" for each of these functions.

My question is whether anyone can come up with a better implementation for this.

For what it's worth I'm using clang++. My version of g++ does not like this.

Here's what I have so far:

#include <string>
#include <deque>
#include <algorithm>
#include <iterator>
#include <iostream>
using namespace std;

template<typename... Policies>
class PolicyDrivenClass
{
   public:

      template<typename T, typename... Types>
      class NameExtractor
      {
         public:
            static deque<string> getNames() 
            {
               deque<string> names = NameExtractor<Types...>::getNames();
               names.push_front(T::name());
               return names;
            }

      };
      template<typename T>
      class NameExtractor<T>
      {
         public:
            static deque<string> getNames() 
            {
               deque<string> ret;
               ret.push_back(T::name());
               return ret;
            }
      };

      deque<string> getNames() const
      {
         return NameExtractor<Policies...>().getNames();
      }
};

class Policy1
{
   public:
      static string name(){return "policy 1";}
};

class Policy2
{
   public:
      static string name(){return "policy 2";}
};

class Policy3
{
   public:
      static string name(){return "policy 3";}
};



int main()
{
   PolicyDrivenClass<Policy1, Policy2, Policy3> c;
   deque<string> names = c.getNames();

   ostream_iterator<string> out (cerr,"\n");
   copy(names.begin(), names.end(), out);
}
like image 359
Craig Wright Avatar asked Jun 07 '12 12:06

Craig Wright


1 Answers

You are right. There are easier ways to get the list of names. The following works with GCC-4.7:

template <typename ...Policies>
struct PolicyDrivenClass
{
    std::deque<std::string> getNames() const 
    {
        return { Policies::name()... };
    }
};

Edit: Changed the declaration part of the function to the old syntax. Personally, I prefer the new syntax:

    auto getNames() const -> std::deque<std::string>;
like image 143
nosid Avatar answered Oct 20 '22 11:10

nosid