I am following this question in order to select the right container, but I am encountering problems.
I have a selector class that must push back into a vector of pointers, but the right one depends on its dimension (1 for vectors, 2 for matrices):
class selector
{
struct formValues : std::vector<coolvector<double>*>, std::vector<coolmatrix<double>*> { };
formValues maps;
public:
selector() { };
template<unsigned int formdim, typename F>
void operator+=(const form<formdim, F> &f)
{
typedef typename form<formdim, F>::storage_type storage_type;
typedef typename std::vector<storage_type*> pointer_type;
// Push to the right vector
formValues<pointer_type> &m = maps;
m.push_back(f.storage.get());
}
};
The forms class have a dimension and a storage, again depending on the dimension, using shared pointers:
template <bool, class if_true, class if_false>
struct type_switch
{
typedef if_false type;
};
template <class if_true, class if_false>
struct type_switch<true, if_true, if_false>
{
typedef if_true type;
};
template <class T> class coolvector {};
template <class T> class coolmatrix {};
template<unsigned int formdim, typename F>
class form
{
public:
form() = delete;
form(const std::string &s) : type(s)
{
storage = std::make_shared<storage_type>();
}
std::string type;
typedef typename type_switch<formdim == 1, coolvector<double>, coolmatrix<double>>::type storage_type;
std::shared_ptr<storage_type> storage;
};
class oneform : public form<1, oneform>
{
public:
oneform() = delete;
oneform(const std::string &s) : form(s) { };
double operator()(unsigned int i) { return i * 2; };
};
class twoform : public form<2, twoform>
{
public:
twoform() = delete;
twoform(const std::string &s) : form(s) { };
double operator()(unsigned int i, unsigned int j) { return i * 2 + j * 20; };
};
The problem is that in the selector::operator+= I get this error:
main.cpp:77:19: error: expected unqualified-id
formValues<pointer_type> &m = maps;
^
Any hints are appreciated!
formValues is not a template, so you can't write formValues<pointer_type>.
You appear to mean
pointer_type& m = maps;
to get the appropriate base class subobject of maps.
Related
Is there a way in the code below to say that I don't care what the V parameter is in void watch(event<T, _> &e)
#include <stdlib.h>
#include <stdio.h>
enum events_a {
A_1,
A_2,
};
enum events_b {
B_1,
B_2,
};
template<typename T, T V>
class event {
public:
T id(void) {
return V;
}
};
template<typename T>
class event_loop {
public:
void watch(event<T, _> &e) {
};
};
class a1 : public event<enum events_a, A_2>
{
};
int
main (int argc, char *argv[])
{
a1 a;
printf("%d\n", a.id());
return 0;
}
What I'm trying to do is that users should be forced to subclass event<T,V> and be forced to give T and V.
However the subclass of event_loop<T>, specifically the method watch, should work with all event<T> regardless of their V.
I don't want to template just the watch function as I want the user to be forced to subclass event_loop.
Bonus achievement if I can somehow make sure all subclasses of event<T> have a unique V. Shooting for the stars... :D
Just create a template argument for it and ignore it.
template<typename T, typename Ignore>
class event_loop {
public:
void watch(event<T, Ignore> &e) {
};
};
You could also template just the function, if you want only the function to be templated
template<typename T>
class event_loop {
public:
template<typename Ignore>
void watch(event<T, Ignore> &e) {
};
};
You could specify a default argument for V and static assert like the way below:
enum events_a {
A_1 = 1,
A_2,
};
enum events_b {
B_1 = 1,
B_2,
};
template<typename T, T V = {}>
class event {
static_assert(V != 0, "You should Define a V");
public:
T id() {
return V;
}
};
template<typename T>
struct event_loop {
void watch(event<T> &e) {}
};
class a1 : public event<enum events_a, A_2> { };
Live Demo
I'm in the process of creating a vector class and am trying to figure out ways to reuse the maximum amount of code for different size vectors.
Here's a basic example:
template<typename T, unsigned int D>
class Vector
{
public:
union {
T v[D];
struct {
/* T x;
* T y;
* T z;
* T w;
*/
};
};
Vector()
{
for(unsigned int i=0; i<D; ++i)
(*this)[i] = T(0);
}
Vector(T scalar)
{
for(unsigned int i=0; i<D; ++i)
(*this)[i] = scalar;
}
inline T operator[](int i) { return (*this).v[i]; }
};
I want the member variables to be publicly accessible. Ex:
Vector<float,2> vec;
printf("X: %.2f, Y: %.2f\n", vec.x, vec.y);
What I'd like to do is something along the lines of this:
template<typename T>
class Vector2 : public Vector<T,2, struct { T x; T y; }> {};
template<typename T>
class Vector3 : public Vector<T,2, struct { T x; T y; T z; }> {};
and have it override a struct in the union:
template<typename T, unsigned int D, struct C>
class Vector
{
public:
union {
T v[D];
// Place the passed struct here
};
};
Is there any feasible way to do this? I do not want to use anything other than the standard library if possible. Thanks in advance.
EDIT: After reading upon all of the answers, I have understood that the way I am using unions is incorrect! Thank you to #M.M for pointing this out. I have since chosen to go a different route, but I have selected the answer that best fit what I was looking for at the time. Once again, thank you for all of the welcomed responses below!
What you are trying to do is not allowed.
Anyway, you can do this:
template<typename T>
struct S { T x; T y; };
template<typename T>
class Vector2 : public Vector<T,2,S<T>> {};
Or this:
template<typename T>
class Vector2 : public Vector<T,2,S> {};
In the second case, Vector can be defined as:
template<typename T, unsigned int D, template<typename> class S>
class Vector {
using MyStruct = S<T>;
// ...
union {
T v[D];
MyStruct myStruct;
};
};
It doesn't scale very well to a large D, but if you're just after the four to six variants I'm imagining, you could partial-specialize a base class:
#include <iostream>
template<typename T, size_t D>
struct VectorBase;
template<typename T>
struct VectorBase<T, 2>
{
constexpr VectorBase() : v{} {}
union {
T v[2];
struct { T x, y; };
};
};
template<typename T>
struct VectorBase<T, 3>
{
constexpr VectorBase() : v{} {}
union {
T v[3];
struct { T x, y, z; };
};
};
template<typename T>
struct VectorBase<T, 4>
{
constexpr VectorBase() : v{} {}
union {
T v[4];
struct { T x, y, z, w; };
};
};
template<typename T, size_t D>
struct Vector : public VectorBase<T, D>
{
using VectorBase<T, D>::v;
using size_type = decltype(D);
using value_type = T;
constexpr Vector() : VectorBase<T,D>{} {}
constexpr Vector(T scalar) {
std::fill(std::begin(v), std::end(v), scalar);
}
constexpr T& operator[](size_type i) const noexcept { return v[i]; }
constexpr const T& operator[](size_type i) noexcept { return v[i]; }
constexpr size_type size() const noexcept { return D; }
constexpr T* data() noexcept { return &v[0]; }
constexpr const T* data() const noexcept { return &v[0]; }
};
template<typename T>
using Vector2 = Vector<T, 2>;
template<typename T>
using Vector3 = Vector<T, 3>;
template<typename T>
using Vector4 = Vector<T, 4>;
int main() {
Vector3<int> v{1};
std::cout << v[0] << ", " << v.z << "\n";
return 0;
}
Live demo: http://ideone.com/T3QHoq
If I understood you correctly your main purpose was to to declare order of fields that corresponds to the array elements of templated class. You cannot do this directly as templates does not accept inline type as parameter. To workaround the problem you could play with non-type template parameters to bind some labels to given index of an array:
#include <cstdio>
#include <unordered_map>
#include <utility>
struct Label { } x, y, z, w;
template <Label&... labels>
struct Pack { };
template <class, class>
struct VectorParent;
template <Label&... labels, size_t... Is>
struct VectorParent<Pack<labels...>, std::index_sequence<Is...>> {
static std::unordered_map<Label *, size_t> label_map;
};
template <Label&... labels, size_t... Is>
std::unordered_map<Label *, size_t> VectorParent<Pack<labels...>, std::index_sequence<Is...>>::label_map = {{&labels, Is}...};
struct LabelNotFound { };
template <class T, size_t N, Label&... labels>
struct Vector:VectorParent<Pack<labels...>, std::make_index_sequence<sizeof...(labels)>> {
static_assert(N == sizeof...(labels),
"the cound of labels should corespond to the number of elements of the vector");
using VectorParent<Pack<labels...>, std::make_index_sequence<sizeof...(labels)>>::label_map;
T t[N];
T &operator->*(Label& l) {
auto it = label_map.find(&l);
if (it == label_map.end())
throw LabelNotFound{};
return t[it->second];
}
};
int main() {
Vector<float,2,x,y> vec;
vec->*x = 10.0f;
printf("X: %.2f, Y: %.2f\n", vec->*x, vec->*y); // prints: X: 10.00, Y: 0.00
//vec->*w = 10.1f; //would throw an exception LabelNotFound
}
I got a BaseType which is templated and want to inheritance it with an ArrayItem class. Since i want to use them as stencil for memory i want the ArrayItem class to know which type we have. So i'd like to specialize the constructor for some of the Template values for example long long.
template<typename T>
class ArrayItem : public BaseType<T>
{
public:
inline ArrayItem(T& t);
inline ETypes getType();
private:
ETypes m_type;
};
And the hpp should look like this:
template <typename T>
ArrayItem<T>::ArrayItem (T& t): BaseType(t)
{
}
template <>
ArrayItem<long long>::ArrayItem(long long& t) : BaseType<long long>(t) // this
{
m_type = INT;
}
template<typename T>
inline ETypes ArrayItem<T>::getType()
{
return m_type;
}
But the how do i do this specialization here?
enum ETypes
{
INT,
BOOL,
OBJECT,
ARRAY,
DOUBLE,
STRING
};
template <typename T>
class BaseType
{
public:
BaseType();
explicit BaseType(T& t);
protected:
union DataUnion
{
T data;
size_t size; //to make it at least 64bit
explicit DataUnion(T& t);
} m_data;
};
template <typename T>
BaseType<T>::DataUnion::DataUnion(T& t)
{
this->data = t;
}
template <typename T>
BaseType<T>::BaseType(T& t) : m_data(t) {}
template<typename T>
class ArrayItem : public BaseType<T>
{
public:
explicit inline ArrayItem(T& t);
inline ETypes getType();
private:
ETypes m_type;
};
template <typename T>
ArrayItem<T>::ArrayItem (T& t): BaseType<T>(t)
{
}
template <>
ArrayItem<long long>::ArrayItem(long long& t) : BaseType<long long>(t) // this
{
m_type = INT;
}
template<typename T>
inline ETypes ArrayItem<T>::getType()
{
return m_type;
}
int main()
{
long long somenumber = 1234;
ArrayItem<long long> item(somenumber);
if(item.getType() == INT)
std::cout<< "inttype";
//after this we can stancil the ptr to a
//BaseType<long long> since we know it's a long here
}
What you have looks right to me, outside of not providing the template arguments to BaseType for the typical case.
Here's a simple demo:
#include <iostream>
template <typename T>
struct B { };
template <typename T>
struct D : B<T> {
D(T );
};
template <typename T>
D<T>::D(T )
: B<T>()
{
std::cout << "def\n";
}
template <>
D<long>::D(long )
: B<long>()
{
std::cout << "hi\n";
}
int main()
{
D<int> i(4); // prints def
D<long> l(5); // prints hi
}
Here is a simplified version of a class template (it has subclasses) that I have:
template<class T>
class Bitmap
{
public:
typedef T pixeltype;
Bitmap(const T* PixelData) : Data(/* PixelFormat enum based on T */) { ... }
virtual ~Bitmap() { ... }
...
protected:
Texture Data;
};
The template argument T to Bitmap can be either class A<X> or A<Y> (possibly a few more in the future), where A is a class template as well. Based on T, aka pixeltype, I need to pass one of the enum values PixelFormatX or PixelFormatY to the constructor of Data, which takes an int.
Is this possible? If not, how could I go about implementing what I described?
For completeness, here's what the subclasses basically look like:
template<class T>
class ColorizableBitmap : public Bitmap<T>
{
public:
typedef T pixeltype;
ColorizableBitmap(const T* PixelData) : Bitmap<T>(PixelData) { ... }
...
};
I generally use a traits struct for that:
template<class T>
struct BitmapTraits
{
};
template<class T, class traits = BitmapTraits<T> >
class Bitmap
{
public:
typedef T pixeltype;
Bitmap(const T* PixelData) : Data(traits::PixelFormat) { ... }
virtual ~Bitmap() { ... }
...
protected:
Texture Data;
};
Then use template specialization to define the traits of each class:
template<>
struct BitmapTraits< A<X> >
{
static const int PixelFormat = PixelFormatX;
};
template<>
struct BitmapTraits< A<Y> >
{
static const int PixelFormat = PixelFormatY;
};
You could do something like:
enum A {
x,y
};
class X {
public:
static A a;
};
class Y {
public:
static A a;
};
A X::a = x;
A Y::a = y;
template <class T>
class Bitmap {
public:
Bitmap(): Data(T::a) {
}
A Data;
};
Edited:
In that case you could do something like:
enum A {
x,y
};
template <const A V>
class X {
public:
static A a;
};
template <const A V>
A X<V>::a = V;
template <class T>
class Bitmap {
public:
Bitmap(): Data(T::a) {
}
A Data;
};
int main() {
Bitmap<X<x>> b;
}
Edited 2:
If I undestrood you right you have two nested class now and still you can do something like:
enum A {
x,y
};
template <typename T>
class B {
public:
typedef T t;
};
template <const A V>
class X {
public:
static A a;
};
template <const A V>
A X<V>::a = V;
template <class T>
class Bitmap {
public:
Bitmap(): Data(T::t::a) {
}
A Data;
};
int main() {
Bitmap<B<X<x>>> b;
}
The alternative is (as Remy Lebeau suggested) template specialization.
I'm trying to implement a hypercubeclass, that is, multidimensional vectors.
I have a problem generalizing it. I'm able to make one for a three dimensional hypercube, but as mentioned, the problem is generalizing it. Could anyone help me? You should be able to write hypercube<4> w(5) to get 4 dimensions and 5 elements in each vector that is 5*5*5*5 elements in total.
Here is the code I have for the three dimensional version:
#include <vector>
using std::vector;
using namespace std;
template <int b>
class Hypercube {
public:
Hypercube(int a) : intvec(a){
for (int i = 0; i<a;i++) {
intvec[i].resize(a);
for (int j = 0;j<a;j++) {
intvec[i][j].resize(a);
}
}
}
vector<vector<int> >& operator[](int i) {
return intvec[i];
}
vector<vector<vector<int> > > intvec;
};
For this to work, you need recursive inheritence to provide the correct vector type and the initialization function. Both work recursively, for which I created a little helper struct called hcube_info:
// hypercube.h
#include <vector>
template<unsigned N>
struct hcube_info;
template<>
struct hcube_info<1>
{ // base version
typedef std::vector<int> type;
static type init(unsigned innerdim, int value = 0){
return type(innerdim, value);
}
};
template<unsigned N>
struct hcube_info
{ // recursive definition, N dimensions
private:
typedef hcube_info<N-1> base;
typedef typename base::type btype;
public:
typedef std::vector<btype> type;
static type init(unsigned innerdim, int value = 0){
return type(innerdim, base::init(innerdim, value));
}
};
As you can see, recursion all the way to the one dimensional base case. We also need to recursively initialize the vector to pass the inner dimension all the way through.
And now the real class, a nice interface around the hcube_info:
template<unsigned N>
struct hypercube
{
private:
typedef hcube_info<N> info;
typedef typename info::type vec_type;
public:
typedef typename vec_type::value_type value_type;
typedef typename vec_type::size_type size_type;
explicit hypercube(unsigned innerdim, unsigned value = 0)
: c(info::init(innerdim, value))
{
}
value_type& operator[](unsigned i){
return c[i];
}
size_type size() const{ return c.size(); }
private:
vec_type c;
};
Test program:
#include "hypercube.h"
#include <iostream>
int main(){
hypercube<4> c(5);
unsigned s = c.size() * // dim 1
c[0].size() * // dim 2
c[0][0].size() * // dim 3
c[0][0][0].size(); // dim 4
std::cout << s << '\n'; // outputs: 625 -> 5 * 5 * 5 * 5 -> 5^4
}
I would suggest something along those lines:
template <typename T, unsigned dim> class HQ {
std::vector<HQ<T,(dim-1)> > vector;
public:
HQ(unsigned size) : vector(size,HQ<T,(dim-1)>(size)) {}
};
template <typename T> class HQ<T,1> {
std::vector<T> vector;
public:
HQ(unsigned size) : vector(size,T()) {}
};
template <typename T> class HQ<T,0> {};
You can then implement your accessors for the first both templates as you wish. You can also make things a bit more simple and robust by allowing zero-dimensional matrices:
template <typename T, unsigned dim> class HQ {
std::vector<HQ<T,(dim-1)> > vector;
public:
HQ(unsigned size) : vector(size,HQ<T,(dim-1)>(size)) {}
};
template <typename T> class HQ<T,0> {
T data;
public:
HQ(unsigned size) : data() {}
};
I imagine an access operator would look something like this:
template <typename T, unsigned dim> HQ<T,(dim-1)>& HQ<T,dim>::operator[](unsigned i) {
return vector[i];
}
template <typename T, unsigned dim> HQ<T,(dim-1)> const& HQ<T,dim>::operator[](unsigned i) const {
return vector[i];
}
such that you can write
HQ<int,4> hq(5);
hq[1][4][2][0] = 77;