2017-04-07 110 views
1

派生類我有一系列的實地驗證每一個看起來像下面的:存儲模板集裝箱

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>()); 
... 

雖然這顯然是亂碼。

問題:

  • 有沒有人用這種模式之前,並有實現這一目標的解決方案?
  • 我應該重新考慮這個設計嗎?
+0

很可能有一個數組和遍歷這一點。 – chris

+0

爲什麼特殊的驗證器例如NameValidator是一個模板?它不應該來自Validator 或它應該驗證的任何類型嗎? – ZivS

+0

@chris - 你能澄清你的意思嗎? – Ryan

回答

0

如果你想有一個容器,你可以吃的指令就像

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

你需要你的類型T是已知的,othewise NameValidator<T>不是一個類型,NameValidator<T>()無法初始化的對象。

所以我想你的validator_map應該是一個變量(靜態?)在模板validator()方法ValidatorManager中。

所以,希望可以semplified,我能想象的最好的是在下面的例子中

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