在模板中存储模板化派生类

时间:2017-04-07 16:56:37

标签: c++ templates generics design-patterns

我有一系列的字段验证器,每个都看起来如下:

template <typename T>
class NameValidator : public Validator<T> {

    ...
    bool validate(const T& msg) const override { ... }
    ...

};

每个验证器必须能够验证不同的消息类型,因此模板参数T

我想创建一个管理器类,作为每个验证器的公共网关。如下所示:

class ValidatorManger {

    ...
    // Calls validate() functions for each field.
    template <typename T>
    bool validate(const T& msg) { ... }
    ...

};

因此,我需要将每个验证器类(例如:NameValidator<T>)存储在某种类型的数据结构中,然后在ValidatorManager::validate()内迭代它们。

有没有办法做到这一点,以便我不必为每种消息类型明确专门化模板?我正在拍摄类似下面的内容

validator_map.insert(std::make_pair("Name", NameValidator<T>));
validator_map.insert(std::make_pair("Age", AgeValidator<T>());
...

虽然这显然是胡言乱语。

问题:

  • 之前有没有人使用过这种模式并有解决方案来实现这个目标?
  • 我应该完全重新考虑这个设计吗?

1 个答案:

答案 0 :(得分:0)

如果你想要一个容器,你可以用

之类的说明食物
validator_map.insert(std::pair("Name", NameValidator<T>()));
validator_map.insert(std::pair("Age", AgeValidator<T>()));

您需要知道您的类型T,其中NameValidator<T>不是类型而NameValidator<T>()无法初始化对象。

所以我认为你的validator_map应该是validator()中模板ValidatorManager方法中的一个变量(静态?)。

所以,希望可以简化,我能想象的最好的是以下示例

#include <set>
#include <vector>
#include <memory>
#include <iostream>

template <typename T>
struct Validator 
 { virtual bool validate (T const &) const = 0; };

template <typename T>
struct NameValidator : public Validator<T>
 {
   bool validate (T const & msg) const override
    { std::cout << "- name (" << msg << ")" << std::endl; return true; }
 };

template <typename T>
struct AgeValidator : public Validator<T>
 {
   bool validate (T const & msg) const override
    { std::cout << "- age  (" << msg << ")" << std::endl; return true; }
 };

struct ValidatorManager
 {
   template <typename T>
   bool validate (T const & msg) const
    {
      static bool first {true};
      static std::vector<std::unique_ptr<Validator<T>>> vvt;

      if ( first )
       {
         vvt.emplace_back( new NameValidator<T>{} );
         vvt.emplace_back( new AgeValidator<T>{} );

         first = false;
       }

      bool ret { true };

      for ( auto const & v : vvt )
         ret &= v->validate(msg);

      return ret;
    }
 };

int main()
 {
   ValidatorManager  vm;

   vm.validate(1);
   vm.validate(2.2);
   vm.validate("3.3");
 }