#include "StdAfx.h"

#include "c:\\mironena\\work\\SelfDev\\C++\\Projects\\Dll\\Export.h"
#pragma comment( lib, "c:\\mironena\\work\\SelfDev\\C++\\build\\bin\\Win32\\Debug\\Dll.lib" )

#include <iostream>
#include <cstring>
#include <string>
#include <set>
#include <algorithm>
#include <sstream>
#include <vector>


#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>


//template< typename Base, typename DerivedTypeDetails >
//class ObjectFactory
//{
//protected:
//
//    typedef void(*InstanceCreatorFunc)(Base*&);
//    typedef typename DerivedTypeDetails::KeyType KeyType;
//
//    struct ObjectType
//    {
//        InstanceCreatorFunc			pCreatorFunc;
//        const DerivedTypeDetails*	pObjectTypeDetails;
//
//        ObjectType()
//            : pCreatorFunc(NULL)
//            , pObjectTypeDetails(NULL)
//        {
//        }
//    };
//
//    //
//    // This is a map which maps strings to functions that create an
//    // object of the specified type.
//    //
//    typedef KeyValueMap< KeyType, ObjectType > ObjectTypeMap;
//
//    //
//    // Declare an additional type definition that is this particular
//    // type of object factory.
//    //
//    typedef ObjectFactory< Base, DerivedTypeDetails > FactoryType;
//
//protected:
//    //
//    // Protected Constructor
//    //
//    ObjectFactory()
//        : m_objectTypeMap()
//    {
//    }
//
//public:
//    //
//    // Here is a helper class used for registering the derived classes
//    // of type _base with the object factory, along with a pointer to a
//    // function that can create an object of that type.
//    //
//    // This is a nested class because it is a registrar for this type of factory,
//    // rather than just a general registrar that can work with any factory.
//    //
//    class Registrar
//    {
//    public:
//        Registrar(const DerivedTypeDetails&	objectTypeDetails,
//            InstanceCreatorFunc		pCreatorFunc)
//            : m_objectTypeDetails(objectTypeDetails)
//            , m_pCreatorFunc(pCreatorFunc)
//            , m_bRegistered(false)
//        {
//            registerClass();
//        }
//
//    public:
//        //
//        // Needed sometimes to force compiler to link in the registrar.
//        //
//        void registerClass()
//        {
//            if (m_bRegistered == false)
//            {
//                ObjectFactory& factory = ObjectFactory::instance();
//                factory.registerClass(m_objectTypeDetails, m_pCreatorFunc);
//                m_bRegistered = true;
//            }
//        }
//
//        bool isRegistered()
//        {
//            return m_bRegistered;
//        }
//
//    public:
//        //
//        // Private data members
//        //
//        const DerivedTypeDetails&	m_objectTypeDetails;
//        InstanceCreatorFunc			m_pCreatorFunc;
//        bool						m_bRegistered;
//    };
//
//public:
//    //
//    // Public type definitions
//    //
//    typedef typename ObjectTypeMap::KeyValueVectorType ObjectTypeVector;
//
//public:
//    //
//    // Public interface
//    //
//
//    //
//    // Singleton pattern static member for obtaining the single instance
//    // of the class.
//    //
//    static ObjectFactory& instance()
//    {
//        static ObjectFactory factory;
//        return factory;
//    }
//
//    //
//    // Destructor
//    //
//    ~ObjectFactory()
//    {
//    }
//
//    //
//    // This method will create an object of the specified type.
//    //
//    Base* createObject(const KeyType& key)
//    {
//        Base* pNewObj = NULL;
//
//        Risk::CSGuard guard(m_cs);
//
//        //
//        // Search for a map entry with the same name
//        //
//        ObjectTypeMap::iterator i = m_objectTypeMap.find(key);
//        if (i != m_objectTypeMap.end())
//        {
//            //
//            // Get a pointer to the creator function
//            //
//            InstanceCreatorFunc pCreatorFunc = (*i).second.pCreatorFunc;
//
//            //
//            // Unlock the critical section before calling the creator function
//            // Note: This may lead to race conditions
//            //
//            guard.unlock();
//
//            //
//            // Now call it to create an object of the specified type
//            //
//            (*pCreatorFunc)(pNewObj);
//        }
//
//        return pNewObj;
//    }
//
//    //
//    // Return a list of the object types this factory can create
//    //
//    void getObjectTypes(ObjectTypeVector& objecTypes)
//    {
//        m_objectTypeMap.convertToVector(objecTypes);
//    }
//
//
//protected:
//    //
//    // Protected helper functions
//    //
//
//    //
//    // This allows the Registrar to register the object creator functions
//    //
//    friend class Registrar;
//
//    //
//    // This method registers the type of objects that this factory
//    // can create.
//    //
//    void registerClass(const DerivedTypeDetails&	objectTypeDetails,
//        InstanceCreatorFunc			pCreatorFunc)
//    {
//        Risk::CSGuard guard(m_cs);
//
//        ObjectType objectType;
//        objectType.pCreatorFunc = pCreatorFunc;
//        objectType.pObjectTypeDetails = &objectTypeDetails;
//
//        m_objectTypeMap.insert(ObjectTypeMap::value_type(KeyType(objectTypeDetails.key), objectType));
//    }
//
//
//private:
//    //
//    // Private data members
//    //
//    CS			m_cs;
//
//    //
//    // This is the map which maps object names to a function
//    // that can create an object of that type.
//    //
//    ObjectTypeMap m_objectTypeMap;
//};


//struct String
//{
//
//	String(const char *str = "")
//	{
//		size_ = strlen( str );
//		str_ = new char[ size_ + 1 ];
//		strncpy( str_, str, size_+ 1 );
//	}
//
//	String(size_t n, char c)
//	{
//		size_ = n;
//		str_ = new char[ size_ + 1]();
//
//		for (int i = 0; i < size_; ++i)
//		{
//			str_[i] = c;
//		}
//		str_[size_ + 1] = '\0';
//	}
//
//	size_t size_;
//	char* str_;
//};

//namespace 
//{
//
//char* getline()
//{
//	char inputSymbol = '\0';
//	int stringLength = 1;
//	char* resultStr = new char[stringLength]();
//
//	while ( std::cin.get(inputSymbol) && inputSymbol != '\n' )
//	{
//		char* tmp = new char[ stringLength + 1 ]();
//
//		strcpy(tmp, resultStr);
//		tmp[ stringLength - 1 ] = inputSymbol;
//		delete[] resultStr;
//		resultStr = tmp;
//		++stringLength;
//	}
//
//	return resultStr;
//}
//
//void removeExtraSpaces(std::string& inputStr)
//{
//	size_t firstNonSpaceSymbol = inputStr.find_first_not_of(' ');
//	
//	if ( firstNonSpaceSymbol != std::string::npos )
//	{
//		inputStr = inputStr.substr( firstNonSpaceSymbol, inputStr.length() - firstNonSpaceSymbol );
//	}
//
//	size_t lastNonSpaceSymbol = inputStr.find_last_not_of(' ');
//	if ( lastNonSpaceSymbol != std::string::npos )
//	{
//		inputStr = inputStr.substr( 0, lastNonSpaceSymbol + 1 );
//	}
//
//	size_t repeatedSpaceLocation = inputStr.find("  ");
//	while( repeatedSpaceLocation != std::string::npos )
//	{
//		inputStr.replace( repeatedSpaceLocation, 2, " " );
//		repeatedSpaceLocation = inputStr.find("  ");
//	}
//}
//
//int** transpose(const int* const* m, size_t r, size_t c)
//{
//	int** resultMatrix = new int *[c];
//	for (unsigned int i = 0; i < c; i++)
//		resultMatrix[i] = new int[r];
//
//
//	for ( unsigned int i = 0; i < r; i++ )
//		for ( unsigned int j = 0; j < c; j++ )
//			resultMatrix[j][i] = m[i][j];
//
//	return resultMatrix;
//}
//
//void swap_min(int** mt, unsigned int m, unsigned int n)
//{
//	int rowNum = 0, minElem = mt[0][0];
//
//	for ( unsigned int i = 0; i < m; i++ )
//	{
//		for ( unsigned int j = 0; j < n; j++ )
//		{
//			if ( mt[i][j] < minElem)
//			{
//				minElem = mt[i][j];
//				rowNum = i;
//			}
//		}
//	}
//
//	if ( rowNum != 0 )
//	{
//		for ( unsigned int i = 0; i < n; ++i )
//		{
//			int tmp = mt[0][i];
//			mt[0][i] = mt[rowNum][i];
//			mt[rowNum][i] = tmp;
//		}
//	}
//}
//
//void outputMatrix(int** mt, int rows, int columns)
//{
//	for (int i = 0; i < rows; ++i )
//	{
//		for (int j = 0; j < columns; ++j)
//		{
//			std::cout << mt[i][j] << " ";
//		}
//		std::cout << std::endl;
//	}
//	std::cout << std::endl;
//}
//
//int** createAndFillMatrix(int rows, int columns)
//{
//	int** matrix = new int*[rows](); 
//	for ( int i = 0; i != rows; ++i )
//		matrix[i] = new int[columns]();
//
//	int k = 1;
//	for (int i = 0; i < rows; ++i )
//	{
//		for (int j = 0; j < columns; ++j)
//		{
//			matrix[i][j] = k;
//			++k;
//		}
//	}
//
//	return matrix;
//}
//
//void createFileMapping(const std::wstring& filePath)
//{
//	int a;
//	std::cin >> a;
//
//	TCHAR szName[] = TEXT("Global\\MyFileMappingObject");
//
//	HANDLE hFile = CreateFile(
//		filePath.c_str(),
//		GENERIC_READ | GENERIC_WRITE,
//		FILE_SHARE_READ | FILE_SHARE_WRITE,
//		NULL,
//		OPEN_EXISTING,
//		0,
//		0 );
//
//	// handle failure
//	if ( hFile == INVALID_HANDLE_VALUE )
//	{
//		_tprintf( TEXT( "Could not create file mapping object (%d).\n" ), GetLastError() );
//	}
//
//	HANDLE hFileMap = CreateFileMapping(
//		hFile,								// use paging file
//		NULL,								// default security
//		PAGE_READWRITE,						// read/write access
//		0,									// maximum object size (high-order DWORD)
//		0,									// maximum object size (low-order DWORD)
//		L"Global\\MyFileMappingObject" );	// name of mapping object
//
//	if ( hFileMap == NULL )
//	{
//		_tprintf( TEXT( "Could not create file mapping object (%d).\n" ), GetLastError() );
//	}
//}
//
//}


template<unsigned long N>
struct binary
{
	static unsigned long const value =
		binary<N / 10>::value << 1 | N % 10;
};

template <> struct binary<0>
{
	static unsigned long const value = 0;
};

int binary_conv(int binary)
{
	if (binary == 0)
		return 0;

	return binary_conv(binary / 10) << 1 | binary % 10;
}

std::vector<std::string>&& xvalue_func()
{
	static std::vector<std::string> vec;
	vec = std::vector<std::string>(2, "Hola");

	return std::move(vec);
}

int main()
{
//*************************************************************************
// 	const int ROWS = 3, COLUMNS = 3;
// 
// 	int** matrix = createAndFillMatrix( ROWS, COLUMNS );
// 	outputMatrix( matrix, ROWS, COLUMNS );
// 
// 	swap_min(matrix, ROWS, COLUMNS);
// 	outputMatrix( matrix, ROWS, COLUMNS );
// 
// 	int** result = transpose(matrix, ROWS, COLUMNS);
// 	outputMatrix( matrix, COLUMNS, ROWS );

//*************************************************************************
// 	std::string someStr;
// 	std::getline( std::cin, someStr );
// 
// 	int** matrixVar; 
// 	removeExtraSpaces( someStr );

//	std::cout << someStr;
//*************************************************************************
//	int myints[] = {10,20,30,30,20,10,10,20};
//	std::multiset<int> int_map(myints, myints+8);
//
//	auto iter = int_map.lower_bound( 20 );
//	std::cout << "Upperbound value: " << *int_map.upper_bound(20) << std::endl;
//	std::cout << "Lowerbound value: " << *iter << std::endl;
//	std::for_each(iter, int_map.end(), [=](int var)
//	{
//		std::cout  << var << " ";
//	});
//*************************************************************************

	std::wcout << binary_conv(101) << std::endl;
	std::wcout << binary<101>::value << std::endl;

//*************************************************************************

	std::vector<std::string> value = xvalue_func();
	value.push_back("Hello");
	std::cout << "size= " << value.size() << std::endl;
	std::vector<std::string>::iterator it = value.begin();
	while (it != value.end()) std::cout << *it++ << std::endl;

	std::vector<std::string>&& v = xvalue_func();
	v.push_back("Guten tag");
	std::cout << "size= " << v.size() << std::endl;
	it = v.begin();
	while (it != v.end()) std::cout << *it++ << std::endl;

	v = xvalue_func();
	std::cout << "size= " << v.size() << std::endl;
	it = v.begin();
	while (it != v.end()) std::cout << *it++ << std::endl;


	return 0;
}