#include <vector>
#include <iostream>

int main () {

	int x0 = 0;
	int x1 = 1;
	int x2 = 2;
	// define a vector of pointers to ints
	std::vector<int*> v_int_ptr(3);
	v_int_ptr[0] = &x0;   // can take the address of an object in memory 
	v_int_ptr[1] = &x1;   // - note that this is NOT a reference, it's a pointer!
	v_int_ptr[2] = &x2;
	// print out the pointed-to values, no need to tell the compiler they are ints
	for (auto pi : v_int_ptr)
		std::cout << pi << " : " << *pi << std::endl;
		
	// a vector of pointers to void (= what ever)
	std::vector<void*> v_int_ptr_2(3);
	v_int_ptr_2[0] = &x0;
	v_int_ptr_2[1] = &x1;
	v_int_ptr_2[2] = &x2;
	// Have to tell by static cast that the values are pointers to int.
	// void is an incomplete type in C++ and there cannot be any objects of type void,
	// therefore, void* is not a pointer-to-object type so it can't be dereferenced!
	for (auto pi : v_int_ptr_2)
		std::cout << pi << " : " << *(static_cast<int*>(pi)) << std::endl;
	
	char ch = 'A';	
	v_int_ptr_2.push_back( &ch );	 // OK - implicit cast to void*
	//v_int_ptr.push_back( &ch );    // error - would need explicit cast
	void* pv = v_int_ptr_2.back();   // get the last value
	// prints the char 'A' correctly :
	std::cout << pv << " : " << *(static_cast<char*>(pv)) << std::endl;
	// prints garbage - what ever there is in the memory in the bytes starting at &ch :
	std::cout << pv << " : " << *(static_cast<int*>(pv)) << std::endl;
	
	// a vector for dynamically allocated objects (from free store)
	std::vector<void *> v_dyn_obj;
	v_dyn_obj.push_back(new int(5));
	v_dyn_obj.push_back(new double(6.0));
	v_dyn_obj.push_back(new char(7));
	// prints out garbage for the second and the third value
	for (auto pdv : v_dyn_obj)
		std::cout << pdv << " : " << *(static_cast<int*>(pdv)) << std::endl;
	
	return 0;
}