I want to design a class PrimitiveType which serves as an abstract class for mathematical entities such as scalar, vector, tensor, and so on to store them in a std::vector<PrimitiveType *> myVector through which I can iterate. For example, having two of these vectors of identical size, say myVector1 and myVector2, I want to be able to do something like
for (size_t i = 0; i < myVector1.size(); i++)
myVector1[i] += myVector2[i];
and don't want to care whether I'm adding scalars, vectors, or tensors. Up to now, I came up with
#include <algorithm>
#include <cstddef>
#include <iostream>
template<class T> class Scalar;
template<class T>
class PrimitiveType
{
protected:
size_t size_;
T *value_;
public:
virtual ~PrimitiveType() = 0;
PrimitiveType & operator+=(const PrimitiveType &primitiveType)
{
for (size_t i = 0; i < size_; i++)
value_[i] += primitiveType.value_[i];
return *this;
}
};
template<class T> PrimitiveType<T>::~PrimitiveType() {};
template<class T>
class Scalar : public PrimitiveType<T>
{
using PrimitiveType<T>::size_;
using PrimitiveType<T>::value_;
public:
Scalar(T value = 0.0)
{
size_ = 1;
value_ = new T(value);
}
~Scalar() { delete value_; }
operator T &() { return *value_; }
};
template<class T>
class Vector : public PrimitiveType<T>
{
using PrimitiveType<T>::size_;
using PrimitiveType<T>::value_;
public:
Vector(T value = 0.0)
{
size_ = 3;
value_ = new T[size_];
std::fill(value_, size_, value);
}
~Vector() { delete[] value_; }
T & operator()(size_t index) { return value_[index]; }
};
int main()
{
Scalar<double> s(3.2);
std::cout << s << std::endl;
static const size_t size = 3;
std::vector<PrimitiveType<double> *> p = std::vector<PrimitiveType<double> *>(size);
for (size_t i = 0; i < size; i++)
{
p[i] = new Scalar<double>();
*(p[i]) += s;
std::cout << *static_cast<Scalar<double> *>(p[i]) << std::endl;
}
}
but I don't think this is a very clean solution. In particular,
1) I would like to be able to use initializer lists in the child classes but get problems with dependent name lookup, e.g.
error: ‘using PrimitiveType::size_’ is not a non-static data member of ‘Scalar’
How to realize something like Scalar(T value = 0.0) : size_(1) , value_(new T(value)) {}?
2) I would actually prefer to make value_ a static array because I know at compile time what size value_ has for Scalar, Vector, ... Of course, this does not hold for PrimitiveType, however, an instance of PrimitiveType gets never created.
Edit: Complete edit because other solution was not ok.
Well, the simplest way for your problem would be to move the storage from the main class to the base class and provide accessor of element:
template <class C>
class PrimitiveType {
public:
PrimitiveType & operator+=(const PrimitiveType &primitiveType) {
if (this->_size() != primitiveType._size()) {
throw "Incompatible type." ;
}
for (size_t i = 0 ; i < this->_size() ; ++i) {
this->_get(i) += primitiveType._get(i) ;
}
return *this ;
}
protected:
virtual C& _get (size_t) = 0 ;
virtual C _get(size_t) const = 0 ;
virtual size_t _size () const = 0 ;
};
Then in Scalar and Vector for example:
template <class C>
class Scalar : PrimitiveType <C> {
C _value ;
public:
Scalar (C const& c) : _value(c) { }
protected:
virtual C& _get (size_t) = 0 { return _value ; }
virtual C _get(size_t) const = 0 { return _value ; }
virtual size_t _size () const = 0 { return 1 ; }
};
template <class C, int N = 3>
class Vector : PrimitiveType <C> {
std::array <C, N> _values ;
public:
Scalar (std::initializer_list <C> l) : _values(l) { }
protected:
virtual C& _get (size_t i) = 0 { return _values(i) ; }
virtual C _get(size_t i) const = 0 { return _values(i) ; }
virtual size_t _size () const = 0 { return _values.size() ; }
};
End of edit.
For your first question, just add a protected constructor in PrimitiveType and call it from your child class:
class PrimitiveType {
protected:
PrimitiveType (/* */) : _values(/* */), /* ... */ { }
};
class Scalar {
public:
Scalar (/* */) : PrimitiveType(/* */) { }
}
For your second questions, add a storage type as second argument templates of primitive type:
template <class C, class S = std::vector <C>>
class PrimitiveType { /* */ }
template <class C>
class Scalar : public PrimitiveType <C, std::array <C, 1>> { /* */ }
Detailled example:
template <class C, class S = std::vector <C>>
class PrimitiveType {
public:
PrimitiveType & operator+=(const PrimitiveType &primitiveType) {
/** Same code as yours. **/
}
protected:
S _values ;
PrimitiveType (std::initializer_list <C> l) : _values(l) { }
};
template <class C>
class Scalar : public PrimitiveType <C, std::array <C, 1>> {
public:
Scalar (C const& c) : PrimitiveType({c}) { }
};
Related
struct PacketBase
{
virtual ~PacketBase() {}
template<class T>
const T& get() const
{
return static_cast<const PacketVal<T>&>(*this).val;
}
template<class T>
void set(const T& rhs)
{
return static_cast<PacketVal<T>>(*this).val = rhs;
}
};
template <typename T>
struct PacketVal : public PacketBase
{
T val;
PacketVal(const T& rhs) : val(rhs) {}
~PacketVal() {}
};
class CResponsePacket
{
private:
std::vector<std::pair<int, const PacketBase*>> m_vPacketData;
public:
void addValue(int n, const PacketBase& packetData)
{
m_vPacketData.emplace_back(std::make_pair(n, &packetData));
}
void print()
{
for ( auto& data : m_vPacketData )
{
std::printf("%d - ", data.first);
std::printf("%s\n", data.second->get<std::string>().c_str());
}
}
};
CResponsePacket has template class member-variable.
int main()
{
CResponsePacket packet;
std::string strAAA("AAA");
PacketVal<std::string> pVal(strAAA);
packet.addValue(1, pVal);
for ( int nIdx = 0; nIdx < 5; ++nIdx )
{
PacketVal<std::string> pp(strAAA);
packet.addValue(nIdx + 1, pp);
}
packet.print();
return 0;
}
The result is
1 - AAA
1 -
2 -
3 -
4 -
5 -
Because the instance is in a loop, memory is destroyed. But this is just an example, and I have to use loop actually. How can I solve this...?
......................
..................
You can make use of std::shared_pointer or std::unique_ptr (depending of your use), and so having the vector looking like this:
std::vector<std::pair<int, std::shared_pointer<PacketBase>>> m_vPacketData;
And so then the addValue method should look like this:
void addValue(int n, const PacketBase& packetData)
{
m_vPacketData.emplace_back(
std::make_pair(
n,
std::make_shared<PacketBase>(packetData)
)
);
}
This will make a copy of packetData on the heap, and store the reference in a shared pointer. If you don't what this copy to be made, then you have to define a new constructor in PacketBase
class PacketBase{
public:
PacketBase(PacketBase&& el): attr(std::move(el.attr))... {...}
}
and then redefining the addValue that accept a rvalue reference
void addValue(int n, PacketBase&& packetData)
{
m_vPacketData.emplace_back(
std::make_pair(
n,
std::make_shared<PacketBase>(std::move(packetData))
)
);
}
And then actually calling the right addValue from main:
for ( int nIdx = 0; nIdx < 5; ++nIdx )
{
PacketVal<std::string> pp(strAAA);
packet.addValue(nIdx + 1, std::move(pp));
}
Or actually just:
for ( int nIdx = 0; nIdx < 5; ++nIdx )
packet.addValue(nIdx + 1, PacketVal<std::string>(strAAA););
This will obviously force you to rewrite the entire class, because you are changing the attribute type... the other way that you can achieve this is switch from
m_vPacketData.emplace_back(std::make_pair(n, &packetData));
to
m_vPacketData.emplace_back(std::make_pair(n, new PacketVal(packetData)));
But you have then remember to delete the objects on the heap or you will have memory leaks
I have an implementation design trouble. I hope you can help me. Suppose I have the following class
class A
{
public:
vector<int> v() const { return m_v; }
bool isValid() const { return m_v.size() > m_components; }
int operator [] (const int index) const { return m_v[index]; }
...
private:
vector<int> m_v;
int m_components;
}
Now I want the m_v vector can be of different types, so I can template the class:
template<typename T>
class A
{
public:
vector<T> v() const { return m_v; }
T operator [] (const int index) const { return m_v[index]; }
...
private:
vector<T> m_v;
int m_components;
}
However, I realized that when the type T is for example double I need to extend class A and add more attributes, for example another vector<bool> m_foo; and change several methods that should use these new attributes.
Here is where I have the doubt. I think I have several options:
Option 1: I can make a non-templated base class A with the implementation of all the common methods, and derive several classes each one for each different type (with its own specific class attributes and method implementations), i.e.: Aint, Adouble, Afloat. This option requires that the vector<...> m_v; is stored at each derived class, and hence I have to replicate several times all the same code to access the m_v; attribute in each derived class. In the example, such methods are only v(), operator [] and isValid(), however in the real problem there are much more.
Option 2: Template specialization. I can specialize the class template for each type and hence provide only the implementation of the specific methods that change depending on the T type. However, this enforces to store a lot of stuff in the template class that is only used if T is of a specific type, i.e. the m_foo vector that is only used when T type is double (in the proposed example). Therefore, I am wasting memory. Moreover, it seems not very elegant or even coherent to implement a template class and provide template class specialization for almost most of the template types and store specific attributes that are only used for specific types.
I don't know if I managed to explain my problem well. Hope so.
Thank you in advance.
Javier.
This kind of depends.
General rule of thumb is asking yourself if "ADouble is-a A". When those have a is-a relationship you should use inheritance.
But you also have type dependency which is not really a "is-a" relationship.
You can also use both options: Having a base class with the common functionality which takes a template argument and having child classes with the additions they need. So you don't need to reimplement all the type dependend functions
So:
template<typename T>
class A
{
public:
vector<T> v() const { return m_v; }
T operator [] (const int index) const { return m_v[index]; }
...
private:
vector<T> m_v;
...
};
class ADouble : public A<double>
{
...
};
Btw: why do you think templates take more memory?
Partially specialise specific operations in your class (without specialising the whole class) with sub-operations.
#include <vector>
namespace detail
{
// general concept of indexing into something
template<class T> struct index_operation;
// indexing into most vectors
template <class T> struct index_operation<std::vector<T>>
{
T& operator()(std::vector<T>& v, std::size_t i) const
{
return v[i];
}
T const& operator()(std::vector<T> const& v, std::size_t i) const
{
return v[i];
}
};
// indexing into a vector<bool>
template <> struct index_operation<std::vector<bool>>
{
std::vector<bool>::reference operator()(std::vector<bool>& v, std::size_t i) const
{
return v[i];
}
std::vector<bool>::const_reference operator()(std::vector<bool> const& v, std::size_t i) const
{
return v[i];
}
};
}
template<typename T>
class A
{
using vector_type = std::vector<T>;
public:
std::vector<T> v() const { return m_v; }
decltype(auto) operator [] (const int index) const
{
auto op = detail::index_operation<vector_type>();
return op(m_v, index);
}
private:
std::vector<T> m_v;
};
I will try to formulate the question with an example closely to my real problem although it becomes a longer post.
Option1: Consider the following class implementation based on templates and template specialization.
template<typename T>
class A
{
public:
A() {}
vector<T> v() const { return m_v; }
bool isValid() const { return m_v.size() >= m_components; }
T operator [] (const int i) const { return m_v[i]; }
T& operator [] (const int i) { return m_v[i]; }
int components() const { return m_components; }
double value() const { return m_value; }
void method1();
private:
vector<T> m_v;
int m_components;
double m_value;
vector<bool> m_indices; // this is only used when T is int
map<int, char> m_map; // this is only used when T is double
queue<int> m_queue; // this is only used when T is bool
};
template<>
void A<int>::method1()
{
for (int i = 0; i < m_components; ++i) m_v.push_back(i);
// stuff only for int case
for (int i = 0; i < m_components; ++i) { i % 2 == 0 ? m_indices[i] = true : m_indices[i] = false; }
}
template<>
void A<double>::method1()
{
for (int i = 0; i < m_components; ++i) m_v.push_back(i);
// stuff only for double case
for (int i = 0; i < m_components; ++i) { i % 2 == 0 ? m_map[i] = 'e' : m_map[i] = 'o'; }
}
template<>
void A<bool>::method1()
{
for (int i = 0; i < m_components; ++i) m_v.push_back(i);
// stuff only for bool case
for (int i = 0; i < m_components; ++i) { i % 2 == 0 ? m_queue.push(1) : m_queue.push(0); }
}
As you can see, there are several methods that are common regardless the T type and involves the use of the m_v vector (methods: v(), isValid(), operator[]). However, there are also other methods (method1()) that have a specific implementation depending on T type, and also requires the use of specific data structures depending on this type (queues, maps, vectors). I see very very ugly the definition of queues, maps, vectors, etc in the class although if they are only used in concrete cases depending the T type.
Option 2: The other alternative:
class A
{
public:
A() {}
int components() const { return m_components; }
double value() const { return m_value; }
virtual void method1() == 0;
protected:
int m_components;
double m_value;
};
/***** Derived A for int case ****/
class Aint : public A
{
public:
Aint() {}
vector<int> v() const { return m_v; }
bool isValid() const { return m_v.size() >= m_components; }
int operator [] (const int i) const { return m_v[i]; }
int& operator [] (const int i) { return m_v[i]; }
void method1();
private:
vector<int> m_v;
vector<bool> m_indices;
};
void Aint::method1()
{
for (int i = 0; i < m_components; ++i) m_v.push_back(i);
for (int i = 0; i < m_components; ++i) { i % 2 == 0 ? m_indices[i] = true : m_indices[i] = false; }
}
/***** Derived A for double case ****/
class Adouble : public A
{
public:
Adouble() {}
vector<double> v() const { return m_v; }
bool isValid() const { return m_v.size() >= m_components; }
double operator [] (const int i) const { return m_v[i]; }
double& operator [] (const int i) { return m_v[i]; }
void method1();
private:
vector<double> m_v;
map<int, char> m_map;
};
void Adouble::method1()
{
for (int i = 0; i < m_components; ++i) m_v.push_back(i);
for (int i = 0; i < m_components; ++i) { i % 2 == 0 ? m_map[i] = 'e' : m_map[i] = 'o'; }
}
/***** Derived A for bool case ****/
class Abool : public A
{
public:
Abool() {}
vector<bool> v() const { return m_v; }
bool isValid() const { return m_v.size() >= m_components; }
bool operator [] (const int i) const { return m_v[i]; }
bool& operator [] (const int i) { return m_v[i]; }
void method1();
private:
vector<bool> m_v;
queue<int> m_map;
};
void Abool::method1()
{
for (int i = 0; i < m_components; ++i) m_v.push_back(i);
for (int i = 0; i < m_components; ++i) { i % 2 == 0 ? m_queue.push(1) : m_queue.push(0); }
}
As you can see, in this case the type specific data structures (queues, maps, etc) are only defined for their required cases (not in the general class template of the Option 1). But, now the m_v vector should be defined at each derived class due to its specific type. Hence, the stuff for accesing and manipulating the vector should be replicated always in all the derived classes although they are always the same (methods v(), isValid(), operator[], etc). It also seems non-well designed.
What is the best design for that purpose?
Thank you
There are some Classes: Array, NumericArray. Array is a template class, and NumericArray is a class inherited from Array designed to take int, double, etc.
Part of Header of NumericArray:
template <class T = int>
class NumericArray : public Array<T>{
private:
T* m_data;
int size;
public:
NumericArray<T> operator * (T factor)const;
};
here are constructors and some functions of NumericArray:
template <class T>
NumericArray<T>::NumericArray(){
m_data = new T[10];
size = 10;
}
template <class T>
NumericArray<T>::NumericArray(int n){
m_data = new T[n];
size = n;
}
template <class T>
NumericArray<T>::NumericArray(const NumericArray<T>& s_data){
m_data = new T[s_data.size];
// assign elements in the source array
for (int i = 0;i<=(s_data.Size()-1 ); i++){
m_data[i] = s_data.m_data[i];
}
size = s_data.Size();
}
/* Destructor */
template <class T>
NumericArray<T>::~NumericArray(){
delete [] m_data;
}
template <class T>
NumericArray<T> NumericArray<T>::operator * (T factor)const{
NumericArray<T> temp(size);
for (int i = 0; i<size;i++){
temp.m_data[i] = (*this)[i] *factor;
}
return temp;
}
And when I call it in the main(), something weird happens. For example:
NumericArray<int> intArray1(10);
NumericArray<int> intArray2;
for(int i =0; i<10;i++){
intArray1[i] = i;
intArray2[i] = i;
}
The 2 arrays do contain numbers 0-9, but if I call
NumericArray intArray4 = intArray1*2;
intArray4 consists of zero(0)s. It seems that the default constructor is called in the function and passed to Array4. And after the operator, Array1 and Array2 are still numbers 0-9
Below are the related code of Array
template class Array{
private:
T* m_data;
int size;
public:
Array(); // constructor
Array(int n); // constructor
Array(const Array<T>& s_data); //Copy Constructor
virtual ~Array(); // destructor
void SetElement(int i, const T& source);
T& GetElement(int i)const;
int Size() const;
int DefaultSize()const;
void DefaultSize(int n);
// Operator overloading
Array<T>& operator = (const Array<T>& source) ;
T& operator [](int i);
const T& operator [] (int i) const;
};
template <class T>
Array<T>::Array(){
// default constructor
m_data = new T[defaultSize]; // initialize T*
size = defaultSize; // initialize integer
}
template <class T>
Array<T>::Array(int n){
// Constructor with arguments
m_data = new T[n];
size = n;
}
template <class T>
Array<T>::Array(const Array<T>& s_data){
// Copy constructor
m_data = new T[s_data.Size()];
// assign elements in the source array
for (int i = 0;i<=(s_data.Size()-1 ); i++){
m_data[i] = T( s_data.m_data[i]);
}
size = s_data.Size();
defaultSize = s_data.Size();
}
template <class T>
T& Array<T>::operator [](int i) {
if (i > size|| i<0){
OutOfBoundsException a;
throw a;
}
return m_data[i];
}
Not sure if provided enough information. Any hint is greatly appreciated.
The easiest way to access base class data members when the base is a (dependent) class template, is a using declaration like this:
#include <iostream>
using namespace std;
template< class Item >
class Base
{
protected:
Item item_;
Base( Item const& v ): item_( v ) {}
};
template< class Item >
class Derived
: public Base< Item >
{
protected:
using Base<Item>::item_;
public:
auto value() const -> Item { return item_; }
Derived( Item const& v ): Base<Item>( v ) {}
};
auto main() -> int
{
Derived<int> const x( 42 );
cout << x.value() << endl;
}
Alternatively you can qualify the access, e.g. this->item_ or Base<Item>::item_.
That said, it’s usually not a good idea to let derived classes access base class data members directly.
Here is the problem: both NumericArray and Array have
T* m_data;
int size;
The function Array::operator[] is called from Array which uses Array::m_data, however the NumericArray::operator* sets NumericAray::m_data. It probably is working as you would expect, but you are reading from the wrong pointer.
Remove the members from NumericArray and make the members protected instead of private in Array. The second part is optional if the implementation is changed a little bit.
This question already has answers here:
In a templated derived class, why do I need to qualify base class member names with "this->" inside a member function?
(2 answers)
Closed 9 years ago.
I am writing template class for a sudoku puzzle, where the template parameters define the size of the rows and columns. I am using g++-4.8 with C++11 enabled.
I have one compiling issue that I worked around, but I would like to understand why it is not working as expected:
My RowIteratorImpl class derives from VirtualLineIteratorImpl, but I cannot access its fields virtualLineIdx and cellInVirtualLineIdx although this should be possible:
class VirtualLineIteratorImpl : public CellIteratorImpl
{
protected:
size_t virtualLineIdx;
size_t cellInVirtualLineIdx;
public:
VirtualLineIteratorImpl(size_t virtualLineIdx)
: virtualLineIdx(virtualLineIdx), cellInVirtualLineIdx(0)
{}
virtual void increment(size_t offset)
{
virtualLineIdx += offset;
}
};
class RowIteratorImpl : public VirtualLineIteratorImpl
{
public:
using VirtualLineIteratorImpl::VirtualLineIteratorImpl;
virtual size_t getCellIdx() const
{
// TODO: does not compile
// return mivTSudoku::getCellIdxInRow(virtualLineIdx, cellInVirtualLineIdx);
return mivTSudoku::getCellIdxInRow(VirtualLineIteratorImpl::virtualLineIdx, VirtualLineIteratorImpl::cellInVirtualLineIdx);
}
};
The compiler generates the following message:
mivSudoku.h: In member function ‘virtual size_t mivTSudoku::RowIteratorImpl::getCellIdx() const’:
mivSudoku.h:85:39: error: ‘virtualLineIdx’ was not declared in this scope
return mivTSudoku::getCellIdxInRow(virtualLineIdx, cellInVirtualLineIdx);
This is the entire class definition:
#ifndef MIVSUDOKU_H
#define MIVSUDOKU_H
#include <bitset>
#include <iterator>
#include <memory>
template<size_t n, size_t m=n>
class mivTSudoku
{
public:
class Cell
{};
static constexpr size_t getCellIdx(size_t rowIdx, size_t colIdx)
{
return rowIdx * dim + colIdx;
}
static constexpr size_t getCellIdxInRow(size_t rowIdx, size_t cellInRowIdx)
{
return getCellIdx(rowIdx, cellInRowIdx);
}
static constexpr size_t getCellIdxInColumn(size_t columnIdx, size_t cellInColumnIdx)
{
return getCellIdx(cellInColumnIdx, columnIdx);
}
static constexpr size_t getCellIdxInBlock(size_t blockIdx, size_t cellInBlockIdx)
{
return getCellIdx((blockIdx / n) * n + (cellInBlockIdx / m), (blockIdx % n) * m + (cellInBlockIdx % m));
}
class CellIteratorImpl
{
public:
virtual CellIteratorImpl* clone() = 0;
virtual void increment(size_t) = 0;
virtual void getCellIdx() const = 0;
};
class AllCellIteratorImpl : public CellIteratorImpl
{
private:
size_t m_cellIdx;
public:
AllCellIteratorImpl()
: m_cellIdx(0)
{}
virtual void increment(size_t offset)
{
m_cellIdx += offset;
}
virtual void getCellIdx() const
{
return m_cellIdx;
}
};
class VirtualLineIteratorImpl : public CellIteratorImpl
{
protected:
size_t virtualLineIdx;
size_t cellInVirtualLineIdx;
public:
VirtualLineIteratorImpl(size_t virtualLineIdx)
: virtualLineIdx(virtualLineIdx), cellInVirtualLineIdx(0)
{}
virtual void increment(size_t offset)
{
virtualLineIdx += offset;
}
};
class RowIteratorImpl : public VirtualLineIteratorImpl
{
public:
using VirtualLineIteratorImpl::VirtualLineIteratorImpl;
virtual size_t getCellIdx() const
{
// TODO: does not compile
//return mivTSudoku::getCellIdxInRow(virtualLineIdx, cellInVirtualLineIdx);
return mivTSudoku::getCellIdxInRow(VirtualLineIteratorImpl::virtualLineIdx, VirtualLineIteratorImpl::cellInVirtualLineIdx);
}
};
typedef std::bidirectional_iterator_tag CellIterator_tag;
typedef std::iterator<CellIterator_tag, Cell> CellIteratorBase;
class Cellterator : public CellIteratorBase
{
private:
typedef CellIteratorBase baseclass;
protected:
mivTSudoku* pSudoku;
CellIteratorImpl* m_pIterImpl;
public:
Cellterator(mivTSudoku* pSudoku, CellIteratorImpl* impl) noexcept
: pSudoku(pSudoku), m_pIterImpl(impl)
{
}
~Cellterator()
{
delete m_pIterImpl;
m_pIterImpl = nullptr;
}
Cellterator(const Cellterator& rhs) noexcept
: pSudoku(pSudoku), m_pIterImpl(rhs.m_pIterImpl->clone())
{}
Cellterator(Cellterator&& rhs) noexcept
: pSudoku(pSudoku), m_pIterImpl(rhs.m_pIterImpl)
{
rhs.m_pIterImpl = nullptr;
}
Cellterator& operator=(const Cellterator& rhs) noexcept
{
if (this == &rhs) return *this;
this->pSudoku = rhs.pSudoku;
this->m_pIterImpl = rhs.m_pIterImpl->clone();
}
Cellterator& operator=(Cellterator&& rhs) noexcept
{
if (this == &rhs) return *this;
this->pSudoku = rhs.pSudoku;
this->m_pIterImpl = rhs.m_pIterImpl;
rhs.m_pIterImpl = 0;
}
size_t getCellIdx() const
{
return m_pIterImpl->getCellIdx();
}
typedef typename baseclass::reference reference;
reference operator*()
{
return pSudoku->m_field[getCellIdx()];
}
reference const operator*() const
{
return pSudoku->m_field[getCellIdx()];
}
typedef typename baseclass::pointer pointer;
pointer operator->()
{
return pSudoku->m_field + getCellIdx();
}
pointer const operator->() const
{
return pSudoku->m_field + getCellIdx();
}
Cellterator& operator++()
{
m_pIterImpl->increment(1);
return *this;
}
Cellterator operator++(int)
{
Cellterator iter;
this->operator++();
return iter;
}
bool operator==(const Cellterator& rhs) const
{
return getCellIdx()==rhs.getCellIdx();
}
bool operator!=(const Cellterator& rhs) const
{
return !operator==(rhs);
}
};
public:
static const size_t dim = n*m;
static const size_t ncells = dim*dim;
private:
Cell m_field[dim];
};
typedef mivTSudoku<3,3> mivSudoku;
#endif // MIVSUDOKU_H
Can some explain to me why?
The issue is that names not depending on a template argument are looked up only when the template arguments are not known. Since your base class depends on a template argument (implicitly by being nested inside a template) the compiler diesn't look at the base class, yet: until the template is instantiated it could get specialuzed, resulting in a completely different class.
The fix is to make the reference to the base member depend on the template argument, e.g., by using this->virtualLineIdx.
I want to have something like that
class A
{
public:
Array& operator()()
{ . . . }
};
class B
{
public:
Element& operator[](int i)
{ ... }
};
template<class T>
class execute
{
public:
output_type = operator()(T& t)
{
if(T == A)
Array out = T()();
else
{
Array res;
for(int i=0 ; i < length; ++i)
a[i] = t[i];
}
}
};
There are two issues here:
meta-function replacing if-else in the execute operator()
return type of execute operator()
Just specialize the template class.
template<class T>
class execute
{};
template<>
class execute<A>
{
A operator()(A& t)
{
/* use A, return A */
}
};
template<>
class execute<B>
{
B operator()(B& t)
{
/* use B, return B */
}
};
Just overload the operator:
// used for As
Array operator()(A& a)
{
// ...
}
// used for everything else
typename T::Element operator()(T& t)
{
// ...
}
If you just need A and B, the second could also be specific to B:
// used for Bs
B::Element operator()(B& b)
{
// ...
}