2017-02-02 5 views
1

Я пытаюсь использовать набор классов шаблонов с переменным параметром. У меня есть несколько опций, которые я мог бы выбрать. Прежде, чем какой-либо из моих шаблонов объявлен или определен, я в настоящее время имею эти прототипы: я знаком с шаблонами, но у меня не было большого опыта использования вариационных типов при работе с шаблонами, поэтому синтаксис иногда меня немного сбивает с толку. Быть, что все они пустые оболочки, которые они сейчас компилируют.Пакет параметров шаблона Variadic для принятия только unsigned ints или size_t как его тип

template<typename ClassType, typename... Args> class MatrixReference; 
template<typename ClassType, typename... Args> class MatrixStorage; 
template<typename ClassType, typename... Args> class MatrixAllocation; 

У меня есть класс пользователя, который будет использовать эти классы в зависимости от намерений использования; это в настоящее время пустая оболочка сейчас, пока я не получить другие классы, определенные правильно с соответствующим поведением:

template<typename ClassType, typename... Args> 
class Matrix {  
}; 

Остальная часть класса от прототипов, показанных выше, унаследует от базового класса, так что выше класс пользователей будет иметь контейнер из них, так что контейнер будет: std::vector<std::unique_ptr<MatrixBase>> или std::vector<shared_ptr<MatrixBase>>, и вектор будет содержать только один из каждого типа из перечисленных прототипов. Например, vector [0] будет содержать MatrixStorage, vector [1] будет контейнером MatrixReference, а vector [2] будет содержать MatrixAllocation. Каждый из этих классов имеет разные обязанности, как показывают их имена. Класс хранения будет содержать исходную стеке элементов. Эталонный класс будет использоваться для ссылки на эти копии. Класс распределения будет использоваться, когда элементы объявлены в куче. Базовый класс выглядит следующим образом:

template <typename ClassType = void> 
class MatrixBase { 
protected: 
    MatrixBase(){} 
    virtual ~MatrixBase(){} 
}; // Matrix 

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

Теперь на объявление моих шаблонов классов: мне действительно нужно использовать один из них здесь, так как все следуют одному и тому же шаблону, но я все равно покажу все 3, так как они в настоящее время пустые оболочки.

// Stores All Of The Contents Of The Matrix 
template<typename ClassType, typename... Args> 
class MatrixStorage : public MatrixBase<ClassType> { 
}; // MatrixStorage  

// Used To Reference The Storage Class Of The Matrix 
template<typename ClassType, typename... Args> 
class MatrixReference : public MatrixBase<ClassType> { 
}; // MatrixReference 

// Used Only When User Wants To Create A Matrix On The Heap 
template<typename ClassType, typename... Args> 
class MatrixAllocation : public MatrixBase<ClassType> { 
}; // MatrixAllocation 

дизайна подход, который я ищу в том, что при использовании этого класса следует шаблону, где первый тип всегда тип данных, матрица будет хранить либо он будет целый, дробный, или некоторый другой пользовательский тип; Следующий параметр, где использование VARIADIC параметра приходит так, что если один экземпляр шаблона как таковые:

Matrix<float,2,2> mat2x2; // Default constructor making it empty 

Это сгенерирует 2х2 размером, Матрицу поплавков

Matrix<int,3,3,3> mat3x3x3; 

Это привело бы к 3x3x3 объемная матрица ints

Таким образом, вариационная часть шаблона всегда будет + целыми числами, а минимальным требованием будет Matrix<type, 1>, где это будет в некотором смысле скалярным или матрицей с одним элементом или матрицей 1x1.

Здесь я предлагаю несколько вариантов. Я мог бы использовать следующий

  • size_t ... N
  • беззнаковое ... D
  • имяТипа ...Args

В настоящее время, как вы можете видеть, это объявлено последним выбором. Так что теперь приходит главный вопрос:

Если я решил использовать параметр обновления, где у меня есть вспомогательный класс как таковой:

template <typename ClassType,typename... Dimensions> 
class DimensionPack { 
public: 
    typename std::tuple<ClassType, std::tuple<Dimensions...> >::type Dim; 
    const unsigned int numarguments = sizeof...(Dimensions); 
}; 

Возникает вопрос; есть ли известный способ сделать Variadic Parameter того же типа, а именно: size_t или unsigned int? Если бы такой пример был бы оценен или ссылка на справочную информацию также помогла бы; Я искал и не нашел ничего полезного, которое достаточно похоже на то, чтобы помочь мне в этом.

Если нет, я не против того, чтобы использовать size_t или unsigned int, но я предпочитающий, чтобы иметь возможность использовать шаблон помощника для упаковки и распаковкой VARIADIC параметров для меня таким образом я не имею реализовать что в каждом классе.

У меня также есть 2 других производных класса, не показанные здесь, но один будет использоваться с протоколированием их на экран, где другой будет использоваться с чтением и анализом из файла и выписыванием файла.

Также в качестве примечания: Для очень больших наборов данных или очень больших размеров матриц: У меня тоже есть этот вспомогательный класс, чтобы использовать для них:

template<typename ClassType, std::size_t bufferSize> 
class MatrixBuffer { 
    static std::vector<ClassType> matrixBuffer = std::vector<ClassType>().reserve(bufferSize); 
}; 

Редактировать

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

+1

Есть ли причина, по которой вы не можете просто использовать 'template '? –

+0

@AlexZywicki Я тоже так думал, но не был уверен, что вспомогательный класс для извлечения и расширения в std :: tuple упростит работу или нет. –

+0

@AlexZywicki Oh; Я почти забыл, но мне нужно проверить, является ли каждое измерение матрицы нечетным или четным. Поэтому вместо того, чтобы просто иметь 'std :: size_t ...«хранение их в пакете параметров для генерации вектора размера этого пакета и для его заполнения 0 для четного или 1 для нечетного также необходимо. Я могу пойти дальше и добавить эту ясность к моему вопросу. –

ответ

2

std::size_t... Args и typename... Args не то же самое. Первый следовало ожидать целые как

Matrix<float,2,2> mat2x2; 

в то время как второй будет ожидать типов вместо.
Конечно, вы могли бы использовать std::integral_constant, но это было бы более многословен:

template <std::size_t N> 
using size = std::integral_constant<std::size_t, N>; 

Matrix<float,size<2>,size<2>> mat2x2; 

С другой стороны, вы можете использовать std::index_sequence:

template<typename ClassType, std::size_t... Dims> 
class Matrix { 
    using Dimensions = std::index_sequence<Dims...>; 
}; 
+0

Да, я это понимаю; но я склоняюсь к использованию класса-помощника-шаблона только для пакета параметров для хранения содержимого в 'std :: tuple', который поможет упаковать и распаковать список параметров. Мне также нужно проверить эти параметры, чтобы увидеть, находятся ли они в диапазоне x> 0 и проверить, являются ли они четными или нечетными и сохранить эти результаты в контейнере. Я бы мог передать это моей вспомогательной функции ... –

+0

Или я смотрю это ... где я мог бы использовать и все же сохранить это в std :: tuple в те же вспомогательные классы и функции. –

+0

@FrancisCugler И в чем проблема с распаковкой 'std :: index_sequence'? –

1

Использование static_assert можно проверить при компиляции время:

template <typename ClassType,typename... Dimensions> 
class DimensionPack { 
     public: 
      DimensionPack(const Dimensions&... args){ 
       checkType<Dimensions...>(args...); 
      } 
      ~DimensionPack(){} 
     private: 
      template<typename T> void checkType(const T& t) { 
       static_assert(std::integral_constant<bool, std::is_same<T, size_t>::value>(), "T is not of type size_t"); 
      } 
      template<typename T, typename... V> void checkType(const T& t, const V&... v) { 
       static_assert(std::integral_constant<bool, std::is_same<T, size_t>::value>(), "T is not of type size_t"); 
       checkType<V...>(v...); 
      } 
    }; 
Смежные вопросы