Я пытаюсь создать базовый класс, который является оболочкой вокруг 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-Dimensional Point:
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, int, size_t, doubles, что угодно?), Потому что, в конце концов, мне действительно все равно, какой там тип. Обратите внимание, что я не могу просто полностью указать ChildClass (например, class MyPointND: public StaticValArray<T,S,MyPointND<T,S>>
), потому что это нарушит мой механизм продвижения типа.
promote
, вы можете использоватьdecltype
:typedef decltype(T+U) type;
внутри структуры. - person Matthieu M.   schedule 15.04.2011