【问题标题】:Policy Based Design with Variadic Templates使用可变参数模板的基于策略的设计
【发布时间】:2012-06-07 12:59:03
【问题描述】:

我有一组同类策略类,我想将它们作为策略传递给一个模板类 PolicyDrivenClass,它接受一些未知数量的策略模板参数。

每个策略都实现了一个“名称”功能,我希望能够在运行时通过 PolicyDriveClass::getNames 查询所有策略的名称。

我有一个可行的实现,但感觉很笨拙,特别是考虑到在我的最终设计中,策略类将实现几个类似于“名称”的函数,尽管可能具有不同的返回类型,并且我的策略驱动类会想要为每个函数提供类似于“getNames”的访问器。

我的问题是是否有人可以为此提出更好的实现。

值得我使用 clang++。我的 g++ 版本不喜欢这样。

这是我目前所拥有的:

#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);
}

【问题讨论】:

  • 您的政策(此处)是无状态的,您是否希望在某个时候拥有有状态的政策? (可能会有点困难)。
  • 更正。上面的代码确实适用于 g++。我之前做的一些事情没有奏效。
  • 我现在不期望有状态的策略,但我可以看到这可能会变得困难。

标签: c++ templates c++11 variadic-templates policy-based-design


【解决方案1】:

你是对的。有更简单的方法来获取名称列表。以下适用于 GCC-4.7:

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

编辑:将函数的声明部分更改为旧语法。就个人而言,我更喜欢新语法:

    auto getNames() const -> std::deque<std::string>;

【讨论】:

  • @KerrekSB:这只是关于可读性。 IMO 新语法提高了可读性,因为您可以专注于最重要的信息 - 函数名称。
  • @KerrekSB 欢迎使用 C++,没有人对任何事情使用相同的语法;)
  • 我只看到它专注于“自动”。那更糟。
  • 我们也需要一种新的变量语法:auto n = 10 -&gt; long int;
  • 我们习惯了左侧有(return)类型的语法,因为常用的静态类型编程语言都使用这种语法。但它一开始是正确的选择吗?有一些编程语言将类型放在另一边,例如function getName(): Stringvar n:Int = 10Pascal 中。较新的语言也使用这种语法,例如斯卡拉。而且我希望在不久的将来更频繁地使用新语法。
猜你喜欢
  • 2014-02-17
  • 2011-01-24
  • 2014-09-30
  • 1970-01-01
  • 2015-08-16
  • 1970-01-01
  • 2011-04-08
  • 2016-02-20
  • 2016-06-30
相关资源
最近更新 更多