2015-10-05 4 views
0

Я работаю на микс-моноблока класса Config Читателя, который поддерживает чтение данных конфигурации из среды, командной строки, файлы и т.д ..C++ VARIADIC шаблон класса дизайн

Я был вид после зЬй :: Тип кортежа дизайн:

template <class... Ts> struct ConfigReader {}; 

template <class T, class... Ts> 
class ConfigReader<T, Ts...> : ConfigReader<Ts...> 
{ 
    public: 
    typedef boost::fusion::set<T, Ts...> sequence_type; 

    ConfigReader(T t, Ts... ts) 
     : ConfigReader<Ts...>(ts...) 
     , parameters_(t, ts...) 
    { 
     this->init(); 
    } 

    private: 
    sequence_type parameters_; 

    void init() 
    { 
     boost::fusion::for_each(parameters_, SetFromEnvironment()); 
     boost::fusion::for_each(parameters_, SetFromCommandLine()); 
     boost::fusion::for_each(parameters_, SetFromConfigFile()); 
    } 
}; 

Но я понял, что я мог бы определить это без рекурсивного наследования

template <class T, class... Ts> 
class ConfigReader<T, Ts...> 
{ 
    public: 
    typedef boost::fusion::set<T, Ts...> sequence_type; 

    ConfigReader(T t, Ts... ts) 
     : parameters_(t, ts...) 
    { 
     this->init(); 
    } 

    template <class Type> 
    typename boost::fusion::result_of::value_at_key<Sequence const, Type>::type get() 
    { 
     return boost::fusion::at_key<Type>(parameters); 
    } 

    private: 
    sequence_type parameters_; 

    void init() 
    { 
     boost::fusion::for_each(parameters_, SetFromEnvironment()); 
     boost::fusion::for_each(parameters_, SetFromCommandLine()); 
     boost::fusion::for_each(parameters_, SetFromConfigFile()); 
    } 
}; 

в последнем случае, кажется, работает лучше, потому что Init() только калла d один раз, который действительно то, что я хочу. Но теперь я смущен относительно того, какие различия между ними? Я что-то теряю без рекурсивного наследования?

Упрощенный использование будет .. (Игнорирование структур типа параметра)

int main() 
{ 
    ConfigReader<Start, End, Resources> configReader(Start(), End("infinity"), Resources()); 

    Start startTime = configReader.get<Start>(); 
} 
+0

Непонятно, что вы делаете. В частности, есть ли причина, по которой вы не просто используете 'std :: tuple'? Что такое 'init()' и где он определен? – Barry

+0

Я добавил еще немного информации. Но действительно ли это влияет на ответ на вопрос о том, какая разница между рекурсивным наследованием и нет? – mike

ответ

0

Рекурсивный подход не имеет смысла. Рассмотрим в качестве примера случай, когда вы хотите:

ConfigReader<A, B, C> reader(A{}, B{}, C{}); 

В рекурсивном случае, вы в конечном итоге с этой иерархии:

ConfigReader<A, B, C> has three readers: A, B, C 
    | 
    | 
    V 
ConfigReader<B, C> has two readers: B, C 
    | 
    | 
    V 
ConfigReader<C> has one reader: C 

У вас есть 6 читателей, когда вы имели в виду лишь 3! То, что вы , вероятно, означает, что когда вы сделали рекурсивную иерархию, для каждого экземпляра есть только один читатель: не все из них. То есть:

template <typename T, typename... Ts> 
struct ConfigReader : ConfigReader<Ts...> { 
    T current; 

    ConfigReader(T t, Ts... ts) 
    : ConfigReader<Ts...>(ts...) 
    , current(t) 
    { } 
}; 

Но то, что вы делаете с набором слияния с форсированием, выполняет это напрямую. Хотя, с C++ 11, вы должны, вероятно, просто придерживаться:

template <typename... T> 
struct ConfigReader { 
    std::tuple<T...> readers; 
}; 

Он должен соответствовать вашей цели.

+0

Да, я начал с использования кортежа, но я думаю, что поддерживающая инфраструктура фьюжн имеет множество утилит, которые мне нужны, например, моя функция get(), которая указывает тип параметра вместо индекса, используемого в кортеже. – mike

+0

@mike C++ 14 добавляет ['std :: get ()'] (http://en.cppreference.com/w/cpp/utility/tuple/get). Вы можете дополнительно реализовать это довольно легко и избегать всех трещин, которые приносит mpl.fusion. – Barry

+0

А интересный в дополнении C++ 14 я этого не знал. Я согласен, у mpl/fusion много багажа. Возможно, я мог бы реализовать эти утилиты (или, по крайней мере, hobble, хотя, учитывая мой опыт работы с шаблонами) – mike

Смежные вопросы