Динамический выбор типа данных на основе шаблона - PullRequest
3 голосов
/ 18 апреля 2011

предположим, у меня есть такой объект:

class Spline {
public:
    Spline(std::size_t const dim);
    // Quite a few functions here. One of those:
    vec operator()(double const t) const; // Returns vector of dimension d
}

Теперь, при большинстве применений этого класса, измерение будет уже определено во время компиляции, поэтому это было бы хорошей идеей (из соображений производительности) изменить класс следующим образом:

template <std::size_t dim>
class Spline {
public:
    Spline();
    // Quite a few functions here. One of those:
    vec::fixed<dim> operator()(double const t) const; // Returns vector of dimension d
}

(Для тех, кому интересно, vec и vec::fixed - это объекты, определенные библиотекой линейной алгебры броненосца).Теперь я хотел бы, чтобы обе версии жили параллельно, чтобы иметь возможность выбирать измерение во время компиляции, а также во время выполнения.Короче говоря, я хотел бы создать эквивалент vec::fixed<dim> как Spline::fixed<dim>, но без реализации всех функций дважды.В частности, я должен был бы выбрать тип возвращаемого значения всех этих функций в зависимости от того, присутствует ли аргумент шаблона или нет.

Есть ли у вас какие-либо идеи о том, как мне это сделать, особенно если подумать о четком и понятном дизайне?(В надежде, что я дал понять, в чем я не совсем уверен.)

Ответы [ 3 ]

3 голосов
/ 18 апреля 2011

Используйте простые черты метаструктуры и специализируйте это.

template<std::size_t dim>
struct spline_return_traits{
  typedef vec::fixed<dim> type;
};

template<>
struct spline_return_traits<0>{ // 0 is a special marker for runtime dimensions
  typedef vec type;
};

template<std::size_t dim>
class Spline_impl{
  typedef typename spline_return_traits<dim>::type spline_return;
public:
  spline_return operator()(double const t) const;
// if <dim> is 0, then the dynamic vec will be chosen as the return type
  // all your functions
};

class Spline : public Spline_impl<0>{ // default is dynamic
public:
  template<int dim>
  struct fixed : public Spline_impl<dim>{
  };
};

Теперь вы просто используете это. :) Каждый оператор, конструктор и функция Spline_impl должны быть доступны в подклассах. Для реализации каждой функции вам нужно выполнить некоторое ветвление, где необходимо выбирать между временем выполнения или фиксированным vec:

if(dim == 0){
  // runtime specific stuff
}else{
  // compile-time specific stuff
}

Использовать как:

Spline dynamic_spline;
Spline::fixed<10> fixed_10_spline;

Единственная проблема в том, что класс Spline будет в два раза больше Spline_impl ...: / Дай подумать, смогу ли я найти решение для этого тоже.
Редактировать : Если вы не хотите, чтобы Spline был удвоен по сравнению с Spline_impl, можно добавить немного многословия и typedef:

class Spline : public Spline_impl<0>{ // default is dynamic size
public:
  template<std::size_t dim>
  struct fixed{
    typedef Spline_impl<dim> type;
  };
};

И использовать как

Spline dynamic_spline;
typename Spline::fixed<10>::type fixed_10_spline;
1 голос
/ 18 апреля 2011

Если я правильно понимаю ваш вопрос, вы хотите struct для использования времени компиляции и выполнения, а также с предпочтительно тем же именем.По моему мнению, вы можете объявить class как template и затем специализировать один из его экземпляров (скажем, size_t = 0xffffffff), который вы, возможно, не используете.Вы можете объявить все свои определения для использования во время выполнения в этом экземпляре.

Например,

template<std::size_t dim = ~0> // choose default dimension(0xffffffff) not to be used
class Spline {
public:
  Spline () {}
  vec::fixed<dim> operator () (double const t) const {}
};
template<>
class Spline<~0> {  // specialize the default dimension for runtime use
public:
  Spline (std::size_t const dim) {}
  vec operator () (double const t) const {}
};

Его можно использовать следующим образом:

Spline<5> o5;  // compile time dimensions
Spline<> o0(3); // run time dimensions (don't mention anything in template)
0 голосов
/ 18 апреля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...