#include <iostream>
#include <cassert>

// The Official proposal
// http://w...content-available-to-author-only...d.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf
const // this is a const object... 
class {
public:
	template<class T> // convertible to any type 
	operator T*() const // of null non-member 
	{
		return 0;
	} // pointer... 

	template<class C, class T> // or any type of null 
	operator T C::*() const // member pointer... 
	{
		return 0;
	}

private:
	void operator&() const; // whose address can't be taken 
} my_nullptr = {}; // and whose name is nullptr


struct Test123 {
	int ABCD, ABC, AB;
	int A;
	int BA, CBA, DCBA;
	struct XYZ {
		char X, Y, Z, W;
	};
	struct {
		int B, C, D;
	};
} test123;


class Test {
	int ABCD;
public:
	void method(void){}

	Test(int val) :ABCD(val){}
	int getABCD(void) const { return ABCD; }
	int get2ABCD(void) const { return ABCD * 2; }
	int get3ABCD(void) const { return ABCD * 3; }
} test(0123);


int main(int argc, char* argv[])
{

	// TEST_my_nullptr
	{
		int a = 321, *p = my_nullptr;
		assert(p == my_nullptr);
		assert(my_nullptr == p);

		p = &a; *p = 0123;
		assert(p != my_nullptr);
		assert(my_nullptr != p);

		p = my_nullptr;

		int(*mainptr)(int argc, char** argv) = my_nullptr;
		assert(mainptr == my_nullptr);
		assert(my_nullptr == mainptr);
	}


	// TEST_my_nullptr_const
	{
		const int a = 321, *p = my_nullptr;
		assert(p == my_nullptr);
		assert(my_nullptr == p);

		p = &a;
		assert(p != my_nullptr);
		assert(my_nullptr != p);

		const int** ptr = my_nullptr;

		assert(ptr == my_nullptr);
		assert(my_nullptr == ptr);

		ptr = &p;
		assert(ptr != my_nullptr);
		assert(my_nullptr != ptr);
		assert(*ptr != my_nullptr);
		assert(my_nullptr != *ptr);

	}


	// TEST_my_nullptr_member
	{
		int Test123::*pINT = my_nullptr;
		assert(pINT == my_nullptr);
		assert(my_nullptr == pINT);

		pINT = &Test123::ABCD;
		assert(pINT != my_nullptr);
		assert(my_nullptr != pINT);

		test123.*pINT = 0123;

		const int Test123::*pCINT = my_nullptr;
		assert(pCINT == my_nullptr);
		assert(my_nullptr == pCINT);

		pCINT = &Test123::ABCD;
		assert(pCINT != my_nullptr);
		assert(my_nullptr != pCINT);

		assert(test123.*pCINT == test123.*pINT);
	}

	// TEST_my_nullptr_Function
{
	void (Test::*pm)(void) = my_nullptr;

	pm = &Test::method;

	int (Test::*pABCD)(void) const = my_nullptr; // This F**k Line In VS2013

	pABCD = &Test::getABCD;

	int a1 = (test.*pABCD)();

	pABCD = &Test::get2ABCD;
	int a2 = (test.*pABCD)();

	pABCD = &Test::get3ABCD;
	int a3 = (test.*pABCD)();

	assert(a1 + a2 == a3);
}

	std::cout << "All Tests for my_nullptr Passed!" << std::endl;
	return 0;
}
