Question

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);
}
Was it helpful?

Solution

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>;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top