2015-04-24 8 views
2

Я работаю над шаблоном проектирования конвейера/потока данных. У меня есть класс вывода данных алгоритма (AlgorithmOutput), который служит интерфейсом между двумя связанными сегментами сети. В частности, он предоставляет набор шаблонов методов getOutput<size_t N>, которые используются для данных, выводимых из объекта «передатчик данных».C++ Специализация частичного шаблона - упрощение дизайна

Текущий дизайн основан на идее, что пользователи получают класс AlgorithmOutput и предоставляют конечное число реализаций шаблона метода getOutput<size_t N>. Я также должен иметь возможность разрешать пользователям предоставлять свои собственные типы возвращаемых данных из метода getOutput (т. Е. Тип возврата не может быть полиморфным). Кроме того, необходимо иметь все реализации getOutput, чтобы иметь возможность доступа к тому же набору данных, который определен как член класса, к которому относятся методы.

Текущее решение использует частичную явную специализацию в классах, полученных пользователем для определения различных реализаций метода getOutput. Хотя решения действительно работают, это слишком сложно. Я хотел бы упростить его и буду признателен за любые идеи о том, как это можно сделать, не теряя функциональности текущего дизайна.

EDIT: Меня беспокоит простота реализации метода getOutput с точки зрения пользователя. Меня не волнует, насколько сложна реализация базовых классов.

Пример реализации производного класса:

class PipeOutputClass: public AlgorithmOutput<PipeOutputClass> 
{ 

public: 

    template <size_t N> 
    auto getOutput(size_t c_Idx) const 
     { 
      return getOutputImpl<N>::apply(this, c_Idx); 
     } 

    template<size_t N, typename S> friend struct getOutputImpl; 

    template<size_t N, typename = void> 
    struct getOutputImpl 
    { 
     static auto apply(
      PipeOutputClass const* p_Self, 
      size_t c_Idx 
      ) 
      { 
       throw std::runtime_error("Wrong template argument."); 
      } 
    }; 

    template <typename S> 
    struct getOutputImpl<0, S> 
    { 
     static std::unique_ptr<double> apply(
      PipeOutputClass const* p_Self, 
      size_t c_Idx 
      ) 
      { 
       std::unique_ptr<double> mydouble(new double(10)); 
       return mydouble; 
      } 
    }; 

    template <typename S> 
    struct getOutputImpl<1, S> 
    { 
     static std::unique_ptr<int> apply(
      PipeOutputClass const* p_Self, 
      size_t c_Idx 
      ) 
      { 
       std::unique_ptr<int> myint(new int(3)); 
       return myint; 
      } 
    }; 

}; 
+0

Что такое параметр шаблона 'S'? – TartanLlama

+0

Как определяется «N»? – Jarod42

+0

@ Jarod42 Если я правильно понял ваш вопрос, нужный 'N' определяется пользователем' getOutputImpl' пользователем (т. Е. Разработчиком класса). Однако есть лучшее решение - см. Принятый ответ. Это может также лучше объяснить то, что я пытался сделать. – user1391279

ответ

3

Вы можете использовать тег диспетчеризации, чтобы избежать необходимости частичной специализации. Упрощенная версия:

//we'll use this to overload functions based on a size_t template param 
template <size_t N> 
struct Size2Type{}; 

class PipeOutputClass 
{ 
public: 
    template <size_t N> 
    auto getOutput(size_t c_Idx) const 
    { 
     //use Size2Type to tag dispatch 
     return getOutputImpl(Size2Type<N>{}, c_Idx); 
    } 

    //default version for when we don't explicitly provide an overload 
    template <size_t N> 
    auto getOutputImpl(Size2Type<N>, size_t c_Idx) const 
    { 
     throw std::runtime_error("Wrong template argument."); 
    } 

    //overload for when N = 0 
    std::unique_ptr<double> getOutputImpl (Size2Type<0>, size_t c_Idx) const 
    { 
     std::unique_ptr<double> mydouble(new double(10)); 
     return mydouble; 
    } 

    //overload for when N = 1 
    std::unique_ptr<int> getOutputImpl (Size2Type<1>, size_t c_Idx) const 
    { 
     std::unique_ptr<int> myint(new int(3)); 
     return myint; 
    } 
}; 
+0

Спасибо. Очень хорошее решение - это помешало мне справиться с проблемой. – user1391279

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

  • Нет связанных вопросов^_^