//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// For any information, contact info@peousware.com
// Any credit or feedback would be appreciated
//

#include <vector>
#include <list>
#include <iostream>
using namespace std;

template<int N> struct typeof_class;
template<class T> struct WrapType { typedef T class_type; };

#define REGISTER_TYPEOF_INTERNAL(N,T) \
	template<> struct typeof_class<N> { typedef WrapType<T>::class_type V; }; \
	char (*typeof_fct(WrapType<T>::class_type &))[N];
#define REGISTER_TYPEOF2(N, T) REGISTER_TYPEOF_INTERNAL(N, T)

#define REGISTER_TYPEOF_BEGIN() class register_dummyclass { static const int i = __COUNTER__; };
#define REGISTER_TYPEOF(T) REGISTER_TYPEOF2(__COUNTER__,T)

#define REGISTER_IT_TYPEOF(x) \
	REGISTER_TYPEOF_ALL(x) \
	REGISTER_TYPEOF_ALL(vector<x>) \
	REGISTER_TYPEOF_ALL(list<x>) \
	REGISTER_TYPEOF_ALL(vector<const x>) \
	REGISTER_TYPEOF_ALL(list<const x>) \
	REGISTER_TYPEOF_ALL(vector<x*>) \
	REGISTER_TYPEOF_ALL(list<x*>) \
	REGISTER_TYPEOF_ALL(vector<const x*>) \
	REGISTER_TYPEOF_ALL(list<const x*>)

#define REGISTER_TYPEOF_ALL(x) \
	REGISTER_TYPEOF(x) \
	REGISTER_TYPEOF(x*)\
	REGISTER_TYPEOF(x const)\
	REGISTER_TYPEOF(const x*)

#define type_of(x) typeof_class<sizeof(*typeof_fct(x))>::V

REGISTER_TYPEOF_BEGIN() // force use of __COUNT__ to be sure it is >= 1

//REGISTER_IT_TYPEOF(size_t) // msvc size_t = unsigned long
REGISTER_IT_TYPEOF(bool)
REGISTER_IT_TYPEOF(char)
REGISTER_IT_TYPEOF(unsigned char)
REGISTER_IT_TYPEOF(short)
REGISTER_IT_TYPEOF(unsigned short)
REGISTER_IT_TYPEOF(int)
REGISTER_IT_TYPEOF(unsigned int)
REGISTER_IT_TYPEOF(long)
REGISTER_IT_TYPEOF(unsigned long)
REGISTER_IT_TYPEOF(float)
REGISTER_IT_TYPEOF(double)

class MyClass { };
REGISTER_IT_TYPEOF(MyClass)

#define foreach(_it_,_collection_) for(type_of(_collection_)::iterator _it_ = _collection_.begin();_it_ != _collection_.end(); ++_it_)

int test_code()
{
	list<int> myList;
	myList.push_back(1);
	myList.push_back(2);

	vector<int> myVector;
	myVector.push_back(1);
	myVector.push_back(2);

	foreach(it, myList)
	{
		cout << *it << endl;
	}
	foreach(it, myVector)
	{
		cout << *it << endl;
	}

	return 0;
}