0
\$\begingroup\$
  • I want a template class that defines the same algorithms, but can work on different type of data stored in a member variable.
  • The exact type of data ideally depends only on a single template parameter.
  • I don't want run time polymorphism (like have an argument of a pointer to base class that can accept all derive class).

Below is my current solution using variadic template. Is there a simpler/better way?

#include <vector>
class Data1 {
public:
    Data1(int size, int stride) 
            : _v(size*stride), _size(size), _stride(stride) {}
    int& operator[](int id) {return _v[id*_stride];}
    const int _size;
private:
    const int _stride;
    std::vector<int> _v;
};

class Data2 {
public:
    Data2(int size) : _v(size), _size(size) {}
    int& operator[](int id) {return _v[id];}
    const int _size;
private:
    std::vector<int> _v;
};

template <typename Data, typename... Data_arg>
class Base_template {
public:
    Base_template(Data_arg...data_arg): _data(data_arg...) {}
    void set_all() {
        for (int i = 0; i < _data._size; ++i) _data[i] = _val;
    }
protected:
    int _val;
    Data _data;
};

class Thing1 : public Base_template<Data1, int, int> {
public:
    Thing1(const int size) 
            : Base_template(size, 3) {
        this->_val = 1;
    }
};
class Thing2 : public Base_template<Data2, int> {
public:
    Thing2(const int size) 
            : Base_template(size) {
        this->_val = 10;
    }
};

int main() {
    Thing1 t1(100);
    t1.set_all();
    Thing2 t2(10);
    t2.set_all();
}

Notes:

  • I use variadic template because the data needs to be initialize.
  • In the simple example above Data2 actually can be replaced by data1 with a stride of 1. But in the actually code, this is not the case.
\$\endgroup\$
  • \$\begingroup\$ I change the design to avoid this situation. Basically make another template class for all types of data. This template class for all types of data has a constructor that takes an enough number of parameters for initializing all types of data. Also found out that the base class cannot have template virtual function that allows overriding in the derived class. So the design in the above code is bad. \$\endgroup\$ – hamster on wheels Feb 14 '17 at 2:11
  • \$\begingroup\$ May be you could add more context to this, since currently it doesn't make much sense. //OT By the way, I've read Data2 as Dota2 \$\endgroup\$ – Incomputable Feb 14 '17 at 7:37
2
\$\begingroup\$

I'm not sure I understand exactly what you're going for, but I think your Base_template has way too many parameters. You have:

template <typename Data, typename... Data_arg>
class Base_template {
public:
    Base_template(Data_arg...data_arg): _data(data_arg...) {}
    void set_all() {
        for (int i = 0; i < _data._size; ++i) _data[i] = _val;
    }
protected:
    int _val;
    Data _data;
};

but I think all you want is:

template <typename Data>
class Base_template {
public:
    template<typename... Args>
    Base_template(Args&&... args): _data(std::forward<Args>(args)...) {}
    void set_all() {
        for (int i = 0; i < _data._size; ++i) _data[i] = _val;
    }
protected:
    int _val;
    Data _data;
};

Also, notice in passing that your naming convention of "leading underscore" might lead you into conflict with reserved identifiers if you're not super careful. I prefer to use "trailing underscore" for private member variables, just so that I don't have to think about the complicated reserved-identifier rules at all.

\$\endgroup\$
1
\$\begingroup\$

I would suggest using iterators and free functions a la stl.

template<class InputIt, class OutputIt>
OutputIt copy(InputIt first, InputIt last, 
              OutputIt d_first)
{
    while (first != last) {
        *d_first++ = *first++;
    }
    return d_first;
}

If you have C++14, generic lambdas might be a better idea, but I don't have experience with those yet.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.