/*
 * ModBusObject.h
 *
 *  Created on: 15 июн. 2017 г.
 *      Author: Ilia Tikhomirov
 */

#ifndef SOURCE_FILES_MODBUSOBJECT_V1_HPP_
#define SOURCE_FILES_MODBUSOBJECT_V1_HPP_

#ifdef __cplusplus

#include <stddef.h>



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

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

template <class T_DataType>
class ModBusSegment
{
protected:
	unsigned short		Addres;
	T_DataType			*Data_ptr;
	unsigned short 		Data_Count;
public:
	ModBusSegment 		*NextSegment_ptr;
	T_DataType *getDataPtr(unsigned short *DataCount_ptr)
	{
		*DataCount_ptr = Data_Count;
		return Data_ptr;
	}
};


/****************************************************************************************************************************************
 Шаблон сегмента ModBus и его специализации
 ****************************************************************************************************************************************/
template <class T_DataType>
class ModBusTable
{
private:
	ModBusSegment<T_DataType> *LastSegment_ptr;   //Указатель на последний сегмент модбас.
public:
	void AddSegment(ModBusSegment<T_DataType> *Segment_ptr)
	{
		if (LastSegment_ptr != NULL)
		{
			Segment_ptr->NextSegment_ptr = LastSegment_ptr;
		}
		LastSegment_ptr = Segment_ptr;
	}

	ModBusTable()
	{
		LastSegment_ptr = NULL;
	}
};

class ModBusTables
{
public:
	ModBusTable<bool> 			InputBits;
	ModBusTable<unsigned short> InputRegs;
	ModBusTable<bool> 			OutputBits;
	ModBusTable<unsigned short> OutputRegs;
};

template <class T_Data, class T_DataType, unsigned short MaxCount>
class  UserModBusSegment
: public ModBusSegment<T_DataType>
{
private:
	T_Data Data[MaxCount];

	unsigned short UserDataCount;

public:

	UserModBusSegment(ModBusTable<T_DataType> *ModBusTable_ptr, unsigned short AddresValue)
	{
		this->Addres 		= AddresValue;
		this->Data_Count 	= 0;
		this->Data_ptr 		= (T_DataType *)Data;

		UserDataCount 		= 0;

		for (unsigned short UserData_id = 0; UserData_id < this->Data_Count; UserData_id++)
		{
			this->Data_ptr[UserData_id] = 0;
		}

		ModBusTable_ptr->AddSegment(this);
	}

	T_Data *getPtr()
	{
		T_Data *Data_ptr;

		if (UserDataCount < MaxCount)
		{
			Data_ptr 			= 	&Data[UserDataCount++];
			this->Data_Count 	+= 	sizeof(Data) / sizeof(T_DataType);
		}
		else
		{
			Data_ptr = NULL;
		}

		return Data_ptr;
	}
};

/**************************************************************************************************************************/
/*INPUT BITS*/
/**************************************************************************************************************************/

template <class T1> class FR;

/**************************************************************************************************************************/
/*INPUT BITS*/
/**************************************************************************************************************************/

template <class T1, class T2 = void>
class ModBusInputBits;

template <class T1>
class ModBusInputBits<FR<T1>, void>
{
public:
	T1 Fram;
};

template <class T1, class T2>
class ModBusInputBits<T1, FR<T2> >
{
public:
	T1 Sram;
	T2 Fram;
};

template <class T1>
class ModBusInputBits<T1, void>
{
public:
	T1 Sram;
};

/**************************************************************************************************************************/
/*INPUT REGISTERS*/
/**************************************************************************************************************************/

template <class T1, class T2 = void>
class ModBusInputRegs;

template <class T1>
class ModBusInputRegs<FR<T1>, void>
{
public:
	T1 Fram;
};

template <class T1, class T2>
class ModBusInputRegs<T1, FR<T2> >
{
public:
	T1 Sram;
	T2 Fram;
};

template <class T1>
class ModBusInputRegs<T1, void>
{
public:
	T1 Sram;
};
/**************************************************************************************************************************/
/*OUTPUT BITS*/
/**************************************************************************************************************************/

template <class T1, class T2 = void>
class ModBusOutputBits;

template <class T1>
class ModBusOutputBits<FR<T1>, void>
{
public:
	T1 Fram;
};

template <class T1, class T2>
class ModBusOutputBits<T1, FR<T2> >
{
public:
	T1 Sram;
	T2 Fram;
};

template <class T1>
class ModBusOutputBits<T1, void>
{
public:
	T1 Sram;
};

/**************************************************************************************************************************/
/*OUTPUT REGISTERS*/
/**************************************************************************************************************************/

template <class T1, class T2 = void>
class ModBusOutputRegs;

template <class T1>
class ModBusOutputRegs<FR<T1>, void>
{
public:
	T1 Fram;
};

template <class T1, class T2>
class ModBusOutputRegs<T1, FR<T2> >
{
public:
	T1 Sram;
	T2 Fram;
};

template <class T1>
class ModBusOutputRegs<T1, void>
{
public:
	T1 Sram;
};

/**************************************************************************************************************************/
/*MODBUS OBJECTS*/
/**************************************************************************************************************************/

template <class T1, class T2 = void, class T3 = void, class T4 = void>
class ModBusObject;

/**************************************************************************************************************************/
/*MODBUS ONE OBJECT TEMPLATES */
/**************************************************************************************************************************/

template <class T1>
class ModBusObject<ModBusInputBits<T1, void>, void,  void, void >
{
public:
	ModBusInputBits<T1, void> *InputBits_ptr;
};

template <class T1>
class ModBusObject<ModBusInputBits<FR<T1>, void >, void,  void, void >
{
public:
	ModBusInputBits<FR<T1>, void > *InputBits_ptr;

	struct
	{
		T1 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

template <class T1, class T2>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, void,  void, void >
{
public:
	ModBusInputBits<T1, FR<T2> > *InputBits_ptr;

	struct
	{
		T2 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

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

template <class T1>
class ModBusObject<ModBusInputRegs<T1, void>, void,  void, void >
{
public:
	ModBusInputRegs<T1, void> *InputRegs_ptr;
};

template <class T1>
class ModBusObject<ModBusInputRegs<FR<T1>, void>, void,  void, void >
{
public:
	ModBusInputRegs<FR<T1>, void> *InputRegs_ptr;

	struct
	{
		T1 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T2>
class ModBusObject<ModBusInputRegs<T1, FR<T2> >, void,  void, void >
{
public:
	ModBusInputRegs<T1, FR<T2> > *InputRegs_ptr;

	struct
	{
		T2 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

/**************************************************************************************************************************/
template <class T1, class T2>
class ModBusObject<ModBusOutputBits<T1, T2>, void,  void, void >
{
public:
	ModBusOutputBits<T1, T2> *OutputBits_ptr;
};

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

template <class T1, class T2>
class ModBusObject<ModBusOutputRegs<T1, T2>, void,  void, void >
{
public:
	ModBusOutputRegs<T1, T2> *OutputRegs_ptr;
};

/**************************************************************************************************************************/
/*MODBUS TWO OBJECTS TEMPLATES */
/**************************************************************************************************************************/

template <class T1, class T3>
class ModBusObject<ModBusInputBits<T1, void>, ModBusInputRegs<T3, void>,  void, void >
{
public:
	ModBusInputBits<T1, void> *InputBits_ptr;
	ModBusInputRegs<T3, void> *InputRegs_ptr;
};

template <class T1, class T3>
class ModBusObject<ModBusInputBits<FR<T1>, void>, ModBusInputRegs<T3, void>,  void, void >
{
public:
	ModBusInputBits<FR<T1>, void > 	*InputBits_ptr;
	ModBusInputRegs<T3, void> 		*InputRegs_ptr;

	struct
	{
		T1 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

template <class T1, class T2, class T3>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusInputRegs<T3, void>,  void, void >
{
public:
	ModBusInputBits<T1, FR<T2> > 	*InputBits_ptr;
	ModBusInputRegs<T3, void> 		*InputRegs_ptr;

	struct
	{
		T2 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

template <class T1, class T3>
class ModBusObject<ModBusInputBits<T1, void >, ModBusInputRegs<FR<T3>, void>,  void, void >
{
public:
	ModBusInputBits<T1, void > 		*InputBits_ptr;
	ModBusInputRegs<FR<T3>, void> 	*InputRegs_ptr;

	struct
	{
		T3 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T3, class T4>
class ModBusObject<ModBusInputBits<T1, void >, ModBusInputRegs<T3, FR<T4> >,  void, void >
{
public:
	ModBusInputBits<T1, void > 		*InputBits_ptr;
	ModBusInputRegs<T3, FR<T4> > 	*InputRegs_ptr;

	struct
	{
		T4 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T3>
class ModBusObject<ModBusInputBits<FR<T1>, void >, ModBusInputRegs<FR<T3>, void >,  void, void >
{
public:
	ModBusInputBits<FR<T1>, void > *InputBits_ptr;
	ModBusInputRegs<FR<T3>, void > *InputRegs_ptr;

	struct
	{
		T1 Bits;
		T3 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T3, class T4>
class ModBusObject<ModBusInputBits<FR<T1>, void >, ModBusInputRegs<T3, FR<T4> >,  void, void >
{
public:
	ModBusInputBits<FR<T1>, void> *InputBits_ptr;
	ModBusInputRegs<T3, FR<T4> > *InputRegs_ptr;

	struct
	{
		T1 Bits;
		T4 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T2, class T3>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusInputRegs<FR<T3>, void >,  void, void >
{
public:
	ModBusInputBits<T1, FR<T2> > *InputBits_ptr;
	ModBusInputRegs<FR<T3>, void > *InputRegs_ptr;

	struct
	{
		T2 Bits;
		T3 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T2, class T3,	class T4>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusInputRegs<T3, FR<T4> >,  void, void >
{
public:
	ModBusInputBits<T1, FR<T2> > *InputBits_ptr;
	ModBusInputRegs<T3, FR<T4> > *InputRegs_ptr;

	struct
	{
		T2 Bits;
		T4 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

/**************************************************************************************************************************/
template <class T1, class T3, class T4>
class ModBusObject<ModBusInputBits<T1, void>, ModBusOutputBits<T3, T4>,  void, void >
{
public:
	ModBusInputBits<T1, void> *InputBits_ptr;
	ModBusOutputBits<T3, T4> *OutputBits_ptr;
};

template <class T1, class T2, class T3,	class T4>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusOutputBits<T3, T4>,  void, void >
{
public:
	ModBusInputBits<T1, FR<T2> > *InputBits_ptr;
	ModBusOutputBits<T3, T4>	 *OutputBits_ptr;

	struct
	{
		T2 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

template <class T1, class T3, class T4>
class ModBusObject<ModBusInputBits<FR<T1>, void>, ModBusOutputBits<T3, T4>,  void, void >
{
public:
	ModBusInputBits<FR<T1>, void> 	*InputBits_ptr;
	ModBusOutputBits<T3, T4>	 	*OutputBits_ptr;

	struct
	{
		T1 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

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

template <class T1, class T3,class T4>
class ModBusObject<ModBusInputBits<T1, void>, ModBusOutputRegs<T3, T4>,  void, void >
{
public:
	ModBusInputBits<T1, void> *InputBits_ptr;
	ModBusOutputRegs<T3, T4> *OutputRegs_ptr;
};

template <class T1, class T3,class T4>
class ModBusObject<ModBusInputBits<FR<T1>, void>, ModBusOutputRegs<T3, T4>,  void, void >
{
public:
	ModBusInputBits<FR<T1>, void> 	*InputBits_ptr;
	ModBusOutputRegs<T3, T4> 		*OutputRegs_ptr;

	struct
	{
		T1 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

template <class T1, class T2, class T3,	class T4>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusOutputRegs<T3, T4>,  void, void >
{
public:
	ModBusInputBits<T1, FR<T2> > 	*InputBits_ptr;
	ModBusOutputRegs<T3, T4> 		*OutputRegs_ptr;

	struct
	{
		T2 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

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

template <class T1, class T3, class T4>
class ModBusObject<ModBusInputRegs<T1, void>, ModBusOutputBits<T3, T4>,  void, void >
{
public:
	ModBusInputRegs<T1, void> 	*InputRegs_ptr;
	ModBusOutputBits<T3, T4> 	*OutputBits_ptr;
};

template <class T1, class T3, class T4>
class ModBusObject<ModBusInputRegs<FR<T1>, void>, ModBusOutputBits<T3, T4>,  void, void >
{
public:
	ModBusInputRegs<FR<T1>, void> 	*InputRegs_ptr;
	ModBusOutputBits<T3, T4> 		*OutputBits_ptr;

	struct
	{
		T1 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T2, class T3,	class T4>
class ModBusObject<ModBusInputRegs<T1, FR<T2> >, ModBusOutputBits<T3, T4>,  void, void >
{
public:
	ModBusInputRegs<T1, FR<T2> > 	*InputRegs_ptr;
	ModBusOutputBits<T3, T4> 		*OutputBits_ptr;

	struct
	{
		T2 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

/**************************************************************************************************************************/
template <class T1, class T3, class T4>
class ModBusObject<ModBusInputRegs<T1, void>, ModBusOutputRegs<T3, T4>,  void, void >
{
public:
	ModBusInputRegs<T1, void> 	*InputRegs_ptr;
	ModBusOutputRegs<T3, T4> 	*OutputRegs_ptr;
};

template <class T1, class T3, class T4>
class ModBusObject<ModBusInputRegs<FR<T1>, void>, ModBusOutputRegs<T3, T4>,  void, void >
{
public:
	ModBusInputRegs<FR<T1>, void> 	*InputRegs_ptr;
	ModBusOutputRegs<T3, T4> 		*OutputRegs_ptr;

	struct
	{
		T1 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T2, class T3,	class T4>
class ModBusObject<ModBusInputRegs<T1, FR<T2> >, ModBusOutputRegs<T3, T4>,  void, void >
{
public:
	ModBusInputRegs<T1, FR<T2> > 	*InputRegs_ptr;
	ModBusOutputRegs<T3, T4> 		*OutputRegs_ptr;

	struct
	{
		T2 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

/**************************************************************************************************************************/
template <class T1, class T2, class T3,	class T4>
class ModBusObject<ModBusOutputBits<T1, T2>, ModBusOutputRegs<T3, T4>,  void, void >
{
public:
	ModBusOutputBits<T1, T2> *OutputBits_ptr;
	ModBusOutputRegs<T3, T4> *OutputRegs_ptr;
};

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

/**************************************************************************************************************************/
/*MODBUS THREE OBJECTS TEMPLATES */
/**************************************************************************************************************************/

template <class T1, class T3, class T5, class T6>
class ModBusObject<ModBusInputBits<T1, void>, ModBusInputRegs<T3, void>,  ModBusOutputBits<T5, T6>, void >
{
public:
	ModBusInputBits<T1, void> *InputBits_ptr;
	ModBusInputRegs<T3, void> *InputRegs_ptr;
	ModBusOutputBits<T5, T6>  *OutputBits_ptr;
};

template <class T1, class T3, class T5, class T6>
class ModBusObject<ModBusInputBits<FR<T1>, void>, ModBusInputRegs<T3, void>,  ModBusOutputBits<T5, T6>, void >
{
public:
	ModBusInputBits<FR<T1>, void > 	*InputBits_ptr;
	ModBusInputRegs<T3, void> 		*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;

	struct
	{
		T1 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

template <class T1, class T2, class T3, class T5, class T6>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusInputRegs<T3, void>,  ModBusOutputBits<T5, T6>, void >
{
public:
	ModBusInputBits<T1, FR<T2> > 	*InputBits_ptr;
	ModBusInputRegs<T3, void> 		*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;

	struct
	{
		T2 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

template <class T1, class T3, class T5, class T6>
class ModBusObject<ModBusInputBits<T1, void >, ModBusInputRegs<FR<T3>, void>,  ModBusOutputBits<T5, T6>, void >
{
public:
	ModBusInputBits<T1, void > 		*InputBits_ptr;
	ModBusInputRegs<FR<T3>, void> 	*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;

	struct
	{
		T3 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T3, class T4, class T5, class T6>
class ModBusObject<ModBusInputBits<T1, void >, ModBusInputRegs<T3, FR<T4> >,  ModBusOutputBits<T5, T6>, void >
{
public:
	ModBusInputBits<T1, void > 		*InputBits_ptr;
	ModBusInputRegs<T3, FR<T4> > 	*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;

	struct
	{
		T4 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T3, class T5, class T6>
class ModBusObject<ModBusInputBits<FR<T1>, void >, ModBusInputRegs<FR<T3>, void >,  ModBusOutputBits<T5, T6>, void >
{
public:
	ModBusInputBits<FR<T1>, void > *InputBits_ptr;
	ModBusInputRegs<FR<T3>, void > *InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;

	struct
	{
		T1 Bits;
		T3 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T3, class T4, class T5, class T6>
class ModBusObject<ModBusInputBits<FR<T1>, void >, ModBusInputRegs<T3, FR<T4> >,  ModBusOutputBits<T5, T6>, void >
{
public:
	ModBusInputBits<FR<T1>, void> 	*InputBits_ptr;
	ModBusInputRegs<T3, FR<T4> > 	*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;

	struct
	{
		T1 Bits;
		T4 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T2, class T3, class T5, class T6>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusInputRegs<FR<T3>, void >,  ModBusOutputBits<T5, T6>, void >
{
public:
	ModBusInputBits<T1, FR<T2> > 	*InputBits_ptr;
	ModBusInputRegs<FR<T3>, void > 	*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;

	struct
	{
		T2 Bits;
		T3 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T2, class T3,	class T4, class T5, class T6>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusInputRegs<T3, FR<T4> >,  ModBusOutputBits<T5, T6>, void >
{
public:
	ModBusInputBits<T1, FR<T2> > 	*InputBits_ptr;
	ModBusInputRegs<T3, FR<T4> > 	*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;

	struct
	{
		T2 Bits;
		T4 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

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


template <class T1, class T3, class T5, class T6>
class ModBusObject<ModBusInputBits<T1, void>, ModBusInputRegs<T3, void>,  ModBusOutputRegs<T5, T6>, void >
{
public:
	ModBusInputBits<T1, void> *InputBits_ptr;
	ModBusInputRegs<T3, void> *InputRegs_ptr;
	ModBusOutputRegs<T5, T6> 	*OutputRegs_ptr;
};

template <class T1, class T3, class T5, class T6>
class ModBusObject<ModBusInputBits<FR<T1>, void>, ModBusInputRegs<T3, void>,  ModBusOutputRegs<T5, T6>, void >
{
public:
	ModBusInputBits<FR<T1>, void > 	*InputBits_ptr;
	ModBusInputRegs<T3, void> 		*InputRegs_ptr;
	ModBusOutputRegs<T5, T6> 		*OutputRegs_ptr;

	struct
	{
		T1 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

template <class T1, class T2, class T3, class T5, class T6>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusInputRegs<T3, void>,  ModBusOutputRegs<T5, T6>, void >
{
public:
	ModBusInputBits<T1, FR<T2> > 	*InputBits_ptr;
	ModBusInputRegs<T3, void> 		*InputRegs_ptr;
	ModBusOutputRegs<T5, T6> 		*OutputRegs_ptr;

	struct
	{
		T2 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

template <class T1, class T3, class T5, class T6>
class ModBusObject<ModBusInputBits<T1, void >, ModBusInputRegs<FR<T3>, void>,  ModBusOutputRegs<T5, T6>, void >
{
public:
	ModBusInputBits<T1, void > 		*InputBits_ptr;
	ModBusInputRegs<FR<T3>, void> 	*InputRegs_ptr;
	ModBusOutputRegs<T5, T6> 		*OutputRegs_ptr;

	struct
	{
		T3 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T3, class T4, class T5, class T6>
class ModBusObject<ModBusInputBits<T1, void >, ModBusInputRegs<T3, FR<T4> >,  ModBusOutputRegs<T5, T6>, void >
{
public:
	ModBusInputBits<T1, void > 		*InputBits_ptr;
	ModBusInputRegs<T3, FR<T4> > 	*InputRegs_ptr;
	ModBusOutputRegs<T5, T6> 		*OutputRegs_ptr;

	struct
	{
		T4 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T3, class T5, class T6>
class ModBusObject<ModBusInputBits<FR<T1>, void >, ModBusInputRegs<FR<T3>, void >,  ModBusOutputRegs<T5, T6>, void >
{
public:
	ModBusInputBits<FR<T1>, void > *InputBits_ptr;
	ModBusInputRegs<FR<T3>, void > *InputRegs_ptr;
	ModBusOutputRegs<T5, T6> 		*OutputRegs_ptr;

	struct
	{
		T1 Bits;
		T3 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T3, class T4, class T5, class T6>
class ModBusObject<ModBusInputBits<FR<T1>, void >, ModBusInputRegs<T3, FR<T4> >,  ModBusOutputRegs<T5, T6>, void >
{
public:
	ModBusInputBits<FR<T1>, void> 	*InputBits_ptr;
	ModBusInputRegs<T3, FR<T4> > 	*InputRegs_ptr;
	ModBusOutputRegs<T5, T6> 		*OutputRegs_ptr;

	struct
	{
		T1 Bits;
		T4 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T2, class T3, class T5, class T6>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusInputRegs<FR<T3>, void >,  ModBusOutputRegs<T5, T6>, void >
{
public:
	ModBusInputBits<T1, FR<T2> > 	*InputBits_ptr;
	ModBusInputRegs<FR<T3>, void > 	*InputRegs_ptr;
	ModBusOutputRegs<T5, T6> 		*OutputRegs_ptr;

	struct
	{
		T2 Bits;
		T3 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T2, class T3,	class T4, class T5, class T6>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusInputRegs<T3, FR<T4> >,  ModBusOutputRegs<T5, T6>, void >
{
public:
	ModBusInputBits<T1, FR<T2> > 	*InputBits_ptr;
	ModBusInputRegs<T3, FR<T4> > 	*InputRegs_ptr;
	ModBusOutputRegs<T5, T6> 		*OutputRegs_ptr;

	struct
	{
		T2 Bits;
		T4 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};


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

template <class T1, class T3,	class T4, class T5, class T6>
class ModBusObject<ModBusInputRegs<T1, void>, ModBusOutputBits<T3, T4>,  ModBusOutputRegs<T5, T6>, void >
{
public:
	ModBusInputRegs<T1, void> *InputRegs_ptr;
	ModBusOutputBits<T3, T4> 	*OutputBits_ptr;
	ModBusOutputRegs<T5, T6> 	*OutputRegs_ptr;
};

template <class T1, class T3,	class T4, class T5, class T6>
class ModBusObject<ModBusInputRegs<FR<T1>, void>, ModBusOutputBits<T3, T4>,  ModBusOutputRegs<T5, T6>, void >
{
public:
	ModBusInputRegs<FR<T1>, void> *InputRegs_ptr;
	ModBusOutputBits<T3, T4> 	*OutputBits_ptr;
	ModBusOutputRegs<T5, T6> 	*OutputRegs_ptr;

	struct
	{
		T1 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T2, class T3,	class T4, class T5, class T6>
class ModBusObject<ModBusInputRegs<T1, FR<T2> >, ModBusOutputBits<T3, T4>,  ModBusOutputRegs<T5, T6>, void >
{
public:
	ModBusInputRegs<T1, FR<T2> > *InputRegs_ptr;
	ModBusOutputBits<T3, T4> 	*OutputBits_ptr;
	ModBusOutputRegs<T5, T6> 	*OutputRegs_ptr;

	struct
	{
		T2 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

/**************************************************************************************************************************/
/*MODBUS FOUR OBJECTS TEMPLATES */
/**************************************************************************************************************************/
template <class T1, class T3, class T5, class T6, class T7, class T8>
class ModBusObject<ModBusInputBits<T1, void>, ModBusInputRegs<T3, void>,  ModBusOutputBits<T5, T6>, ModBusOutputRegs<T7, T8>  >
{
public:
	ModBusInputBits<T1, void> 	*InputBits_ptr;
	ModBusInputRegs<T3, void> 	*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 	*OutputBits_ptr;
	ModBusOutputRegs<T7, T8>	*OutputRegs_ptr;
};

template <class T1, class T3, class T5, class T6, class T7, class T8>
class ModBusObject<ModBusInputBits<FR<T1>, void>, ModBusInputRegs<T3, void>,  ModBusOutputBits<T5, T6>, ModBusOutputRegs<T7, T8>  >
{
public:
	ModBusInputBits<FR<T1>, void > 	*InputBits_ptr;
	ModBusInputRegs<T3, void> 		*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;
	ModBusOutputRegs<T7, T8>		*OutputRegs_ptr;

	struct
	{
		T1 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

template <class T1, class T2, class T3, class T5, class T6, class T7, class T8>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusInputRegs<T3, void>,  ModBusOutputBits<T5, T6>, ModBusOutputRegs<T7, T8>  >
{
public:
	ModBusInputBits<T1, FR<T2> > 	*InputBits_ptr;
	ModBusInputRegs<T3, void> 		*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;
	ModBusOutputRegs<T7, T8>		*OutputRegs_ptr;

	struct
	{
		T2 Bits;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
	}
};

template <class T1, class T3, class T5, class T6, class T7, class T8>
class ModBusObject<ModBusInputBits<T1, void >, ModBusInputRegs<FR<T3>, void>,  ModBusOutputBits<T5, T6>, ModBusOutputRegs<T7, T8>  >
{
public:
	ModBusInputBits<T1, void > 		*InputBits_ptr;
	ModBusInputRegs<FR<T3>, void> 	*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;
	ModBusOutputRegs<T7, T8>		*OutputRegs_ptr;

	struct
	{
		T3 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T3, class T4, class T5, class T6, class T7, class T8>
class ModBusObject<ModBusInputBits<T1, void >, ModBusInputRegs<T3, FR<T4> >,  ModBusOutputBits<T5, T6>, ModBusOutputRegs<T7, T8>  >
{
public:
	ModBusInputBits<T1, void > 		*InputBits_ptr;
	ModBusInputRegs<T3, FR<T4> > 	*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;
	ModBusOutputRegs<T7, T8>		*OutputRegs_ptr;

	struct
	{
		T4 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T3, class T5, class T6, class T7, class T8>
class ModBusObject<ModBusInputBits<FR<T1>, void >, ModBusInputRegs<FR<T3>, void >,  ModBusOutputBits<T5, T6>, ModBusOutputRegs<T7, T8>  >
{
public:
	ModBusInputBits<FR<T1>, void > 	*InputBits_ptr;
	ModBusInputRegs<FR<T3>, void > 	*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;
	ModBusOutputRegs<T7, T8>		*OutputRegs_ptr;

	struct
	{
		T1 Bits;
		T3 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T3, class T4, class T5, class T6, class T7, class T8>
class ModBusObject<ModBusInputBits<FR<T1>, void >, ModBusInputRegs<T3, FR<T4> >,  ModBusOutputBits<T5, T6>, ModBusOutputRegs<T7, T8>  >
{
public:
	ModBusInputBits<FR<T1>, void> 	*InputBits_ptr;
	ModBusInputRegs<T3, FR<T4> > 	*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;
	ModBusOutputRegs<T7, T8>		*OutputRegs_ptr;

	struct
	{
		T1 Bits;
		T4 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T2, class T3, class T5, class T6, class T7, class T8>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusInputRegs<FR<T3>, void >,  ModBusOutputBits<T5, T6>, ModBusOutputRegs<T7, T8>  >
{
public:
	ModBusInputBits<T1, FR<T2> > 	*InputBits_ptr;
	ModBusInputRegs<FR<T3>, void > 	*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;
	ModBusOutputRegs<T7, T8>		*OutputRegs_ptr;

	struct
	{
		T2 Bits;
		T3 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

template <class T1, class T2, class T3,	class T4, class T5, class T6, class T7, class T8>
class ModBusObject<ModBusInputBits<T1, FR<T2> >, ModBusInputRegs<T3, FR<T4> >,  ModBusOutputBits<T5, T6>, ModBusOutputRegs<T7, T8>  >
{
public:
	ModBusInputBits<T1, FR<T2> > 	*InputBits_ptr;
	ModBusInputRegs<T3, FR<T4> > 	*InputRegs_ptr;
	ModBusOutputBits<T5, T6> 		*OutputBits_ptr;
	ModBusOutputRegs<T7, T8>		*OutputRegs_ptr;

	struct
	{
		T2 Bits;
		T4 Regs;
	} Defaults;

	void DefaultsApply(void)
	{
		InputBits_ptr->Fram = Defaults.Bits;
		InputRegs_ptr->Fram = Defaults.Regs;
	}
};

/**************************************************************************************************************************/
/*MODBUS TREE OBJECTS TABLE TEMPLATES */
/**************************************************************************************************************************/

template <class T1, unsigned short MaxCount = 1> class ModBusObjectTables;

template <class T1, class T2, class T3,	class T4, class T5, class T6, class T7, class T8, unsigned short MaxCount>
class ModBusObjectTables
		<
			ModBusObject<ModBusInputBits<T1, T2>, ModBusInputRegs<T3, T4>, ModBusOutputBits<T5, T6>, ModBusOutputRegs<T7, T8> >,
			MaxCount
		>
{
private:

	unsigned short Count;

	ModBusTables  *ModBusTable_ptr;
	UserModBusSegment<ModBusInputBits<T1, T2>, 	bool, 				MaxCount> InputBits;
	UserModBusSegment<ModBusInputRegs<T3, T4>, 	unsigned short, 	MaxCount> InputRegs;
	UserModBusSegment<ModBusOutputBits<T5, T6>, bool, 				MaxCount> OutputBits;
	UserModBusSegment<ModBusOutputRegs<T7, T8>, unsigned short, 	MaxCount> OutputRegs;

public:

	ModBusObjectTables(ModBusTables *Table_ptr, 	unsigned short 	InputBits_Adr,	unsigned short 	InputRegs_Adr,
													unsigned short 	OutputBits_Adr,	unsigned short 	OutputRegs_Adr):
													InputBits(&Table_ptr->InputBits, 	InputBits_Adr),
													InputRegs(&Table_ptr->InputRegs, 	InputRegs_Adr),
													OutputBits(&Table_ptr->OutputBits, 	OutputBits_Adr),
													OutputRegs(&Table_ptr->OutputRegs, 	OutputRegs_Adr)

	{
		Count = 0;
	}

	ModBusObject<ModBusInputBits<T1, T2>, ModBusInputRegs<T3, T4>, ModBusOutputBits<T5, T6>, ModBusOutputRegs<T7, T8> >
	*getObjectPointer(void)
	{
		ModBusObject<ModBusInputBits<T1, T2>, ModBusInputRegs<T3, T4>, ModBusOutputBits<T5, T6>, ModBusOutputRegs<T7, T8> >
		*Object_ptr = new ModBusObject<ModBusInputBits<T1, T2>, ModBusInputRegs<T3, T4>, ModBusOutputBits<T5, T6>, ModBusOutputRegs<T7, T8> >();

		//TODO организовать конструктор в ModBusObject который занимается энергонезависимой памятью

		Object_ptr->InputBits_ptr 	= InputBits.getPtr();
		Object_ptr->InputRegs_ptr 	= InputRegs.getPtr();
		Object_ptr->OutputBits_ptr 	= OutputBits.getPtr();
		Object_ptr->OutputRegs_ptr 	= OutputRegs.getPtr();

		Count++;

		return Object_ptr;
	}
};

struct Hello
{
    int toString() { return 0; }
};

struct Generic {};

template <class Type>
class TypeHasToString
{
    // This type won't compile if the second template parameter isn't of type T,
    // so I can put a function pointer type in the first parameter and the function
    // itself in the second thus checking that the function has a specific signature.
    template <typename T, T> struct TypeCheck;

    typedef char Yes;
    typedef long No;

    // A helper struct to hold the declaration of the function pointer.
    // Change it if the function signature changes.
    template <typename T> struct ToString
    {
        typedef void (T::*fptr)();
    };

    template <typename T> static Yes HasToString(TypeCheck< typename ToString<T>::fptr, &T::toString >*);
    template <typename T> static No  HasToString(...);

public:
    static bool const value = (sizeof(HasToString<Type>(0)) == sizeof(Yes));
};
#endif

#endif /* SOURCE_FILES_MODBUSOBJECT_V1_HPP_ */
