Я пытаюсь создать базовый класс, который является оберткой вокруг std :: array, которая перегружает группу общих арифметических операторов. Конечный результат будет похож на std :: valarray, но со статическим размером. Я делаю это, потому что я создаю целый ряд дочерних классов для моей библиотеки, которые в итоге копируют эту функциональность. Например, мне нужно создать класс MyPixel и класс MyPoint, оба из которых по сути являются массивами статического размера, с которыми я могу выполнять арифметику.
Мое решение заключается в создании базового класса StaticValArray, из которого могут быть получены MyPoint и MyPixel. Однако, чтобы запретить пользователям добавлять MyPoint в MyPixel, я использую шаблон CRTP как таковой:
template<class T1, class T2>
struct promote
{
typedef T1 type; // Assume there is a useful type promotion mechanism here
};
template<class T, size_t S, template<typename... A> class ChildClass>
class StaticValArray : public std::array<T,S>
{
public:
// Assume there are some conversion, etc. constructors here...
template<class U>
StaticValArray<typename promote<T,U>::type,S,ChildClass> operator+
(StaticValArray<U,S,ChildClass> const & rhs)
{
StaticValArray<typename promote<T,U>::type,S,ChildClass> ret = *this;
std::transform(this->begin(), this->end(),
rhs.begin(), ret.begin(), std::plus<typename promote<T,U>::type>());
return ret;
}
// More operators....
};
Это довольно круто, потому что у ChildClass могут быть любые произвольные параметры шаблона класса, и это будет работать. Например:
template<class T, class U>
class MyClassTwoTypes : public StaticValArray<T,3,MyClassTwoTypes>
{ };
template<class T, class U>
class MyClassTwoTypes2 : public StaticValArray<T,3,MyClassTwoTypes2>
{ };
int main()
{
MyClassTwoTypes<int, float> p;
MyClassTwoTypes<double, char> q;
auto z = p + q;
MyClassTwoTypes2<double, char> r;
// r += q; // <-- Great! This correctly won't compile
return 0;
}
Моя проблема заключается в следующем: я хотел бы вставить некоторый ChildClass в бит CRTP StaticValArray, который не обязательно имеет только классы в качестве параметров шаблона. Например, рассмотрим этот класс N-мерных точек:
template<class T, size_t S>
class MyPointND : public StaticValArray<T,S,MyPointND>
{ };
К сожалению, это не скомпилируется, потому что size_t не является именем типа - я получаю ошибку компилятора:
type/value mismatch at argument 3 in template parameter list for ‘template<class T, long unsigned int S, template<class ... A> class ChildClass> class StaticValArray’
test.C:36:54: error: expected a template of type ‘template<class ... A> class ChildClass’, got ‘template<class T, long unsigned int S> class MyPointND’
Есть ли какой-либо способ создать пакет параметров шаблона шаблона с переменным числом элементов, который может быть абсолютно любым (typenames, ints, size_t's, doubles, что угодно?), Потому что в конце концов мне действительно все равно, какой тип там. Обратите внимание, что я не могу просто полностью указать ChildClass (например, class MyPointND: public StaticValArray<T,S,MyPointND<T,S>>
), потому что это нарушит мой механизм продвижения типов.