A minimum iterator template that works with ostream_iterator


This iterator works with std::ostream_iterator to get the container’s content printed to cout.
It’s minimum because it stops working if I take one more element out.
Minimum snippets is best to show how things work under the hood.

template <class T> class CMyContainer
{
public:
	enum {MAX = 2}; //only hold two elements
protected:
    T maData[MAX];
public:
    CMyContainer<T>(const T& t1, const T& t2)
	{
		maData[0] = t1; maData[1] = t2; //pre-initialized to only 2 element
	}
    class iterator;
    iterator begin()
	{
		return iterator(0, this);
	}
    iterator end()
	{
		return iterator(MAX, this);
	}
};
template <class T> class CMyContainer<T>::iterator
{
    CMyContainer<T> * mpContainer;
    int miIndex;
public:
	typedef std::forward_iterator_tag iterator_category;
	typedef void value_type;
	typedef void difference_type;
	typedef void distance_type;
	typedef void pointer;
	typedef void reference;
    iterator () {}
    iterator (int iIndex, CMyContainer<T> * c): miIndex(iIndex), mpContainer(c) {}
    bool operator==(const iterator & z)
	{
		return miIndex == z.miIndex;
	}
    bool operator!=(const iterator & z)
	{
		return !operator==(z);
	}
    void operator++()
	{
		++ miIndex;
    }
    T& operator*()
	{
		return mpContainer->maData[miIndex];
	}
};

void TestCustomIterator()
{
	CMyContainer<int> b(1, 2);
	CMyContainer<int>::iterator it;
	ostream_iterator<int> o(cout, " ");
	copy(b.begin(), b.end(), o); //this line prints 1 2 (content of b)
}
Advertisements

What if virtual functions in both base classes have the same name?


If virtual functions in both base classes have the same name, the sub classe cannot implement separate functions for the two base classes, while C# has no this problem.

enum { EBASE1, EBASE2, EBASE3, EBASE4 };
struct CMultiBase1
{
	virtual int f()
	{
		return EBASE1;
	};
};
struct CMultiBase2
{
	virtual int f()
	{
		return EBASE2;
	};
};

struct CMultiSub: CMultiBase1, CMultiBase2
{
	int f() //cannot to say to overrides f() for CMultiBase1 or CMultiBase2.
	{       //but with C#, CBase1 or CBase2 can be indicated explicitly
		return EBASE3;
	};
};
void TestMulti()
{
	CMultiSub s;
	CMultiBase1 *p1 = &s;
	CMultiBase2 *p2 = &s;
	_ASSERT(p1->f() == EBASE3);
	_ASSERT(p2->f() == EBASE3);
}

However, C#’s answer for this problem seems redundant, because this problem can be solved by adding another layer.
We replace CMultiSub and TestMulti() above with the following code to solve the problem.

struct CMultiBase1a: CMultiBase1
{
	int f()
	{
		return f1a();
	};
	virtual int f1a() = 0;
};
struct CMultiBase2a: CMultiBase2
{
	int f()
	{
		return f2a();
	};
	virtual int f2a() = 0;
};
struct CMultiSub: CMultiBase1a, CMultiBase2a
{
	int f1a()
	{
		return EBASE4; //for CMultiBase1
	};
	int f2a()
	{
		return EBASE5;  //for CMultiBase2
	};
};
void TestMulti()
{
	CMultiSub s;
	CMultiBase1 *p1 = &s;
	CMultiBase2 *p2 = &s;
	_ASSERT(p1->f() == EBASE4); //for CMultiBase1
	_ASSERT(p2->f() == EBASE5); //for CMultiBase2
}

By adding another layer, CMultiBase1a and CMultiBase2a, we can differentiate the two f() in CMultiBase1 and CMultiBase2.

std::forward vs static_cast


For perfect forwarding, I am still trying to give an use case in which std::forward<T> works but static_cast<T&&> doesn’t.
It was suggested just to use static_cast<T&&> to implement std::forward<T>, but it had problems.
I’d like to pin point the problem with┬áthe simplest snippet.
It’s very much appreciated if you have a solution to share with me.

template calculates 4 + 3 + 2 + 1


This is a “hello world” for template metaprogramming.
MetaFunc() return 10 because (4 + 3 + 2 + 1) equals 10.

template<int n>
int MetaFunc()
{
	return n +  MetaFunc<n-1>();
}
template<>
int MetaFunc<1>()
{
	return 1;
}
int TestMetaFunc()
{
	return MetaFunc<4>(); //4 + 3 + 2 + 1 == 10
}