Шаблоны классов и добавление библиотеки в проект

Всем привет! Понадобилось добавить библиотеку в проект, но пишу AVRStudio 7 и для atmega8a, столкнулся с некоторыми проблемами… Библиотека для радио передатчика 433MHz, и суть такова что с начало в лоб хотел её вставить, но выхватил тут же ошибку:

Severity    Code    Description Project File    Line
Error       multiple definition of `fastRead(unsigned char)'    Fe_wate_house_atmega8_433MHz    G:\FastIO.h 31
Error       multiple definition of `fastWrite(unsigned char, bool)' Fe_wate_house_atmega8_433MHz    G:\FastIO.h 31
Error       multiple definition of `G433_crc8_byte(unsigned char&, unsigned char)'  Fe_wate_house_atmega8_433MHz    G:\FastIO.h 31
Error       multiple definition of `G433_crc8(unsigned char*, unsigned char)'   Fe_wate_house_atmega8_433MHz    G:\FastIO.h 31
Error       multiple definition of `G433_crc_xor(unsigned char*, unsigned char)'    Fe_wate_house_atmega8_433MHz    G:\FastIO.h 31

Сами два файла библиотеки:

FastIO.h
#ifndef FastIO_H_
#define FastIO_H_

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
#define bit(b) (1UL << (b))

bool fastRead(const uint8_t pin);               // быстрое чтение пина
void fastWrite(const uint8_t pin, bool val);    // быстрая запись

// ================================================================
bool fastRead(const uint8_t pin) {
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined (__AVR_ATmega8A__)
    if (pin < 8) return bitRead(PIND, pin);
    else if (pin < 14) return bitRead(PINB, pin - 8);
    else if (pin < 20) return bitRead(PINC, pin - 14);

#elif defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny13__)
    return bitRead(PINB, pin);

#endif
    return 0;
}


void fastWrite(const uint8_t pin, bool val) {
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined (__AVR_ATmega8A__)
    if (pin < 8) bitWrite(PORTD, pin, val);
    else if (pin < 14) bitWrite(PORTB, (pin - 8), val);
    else if (pin < 20) bitWrite(PORTC, (pin - 14), val);

#elif defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny13__)
    bitWrite(PORTB, pin, val);
        
#endif
}

#endif /*FastIO_H_*/
Gyver433.h
#ifndef Gyver433_H_
#define Gyver433_H_

#include "main.h"
#include "FastIO.h"


uint8_t G433_crc8(uint8_t *buffer, uint8_t size);       // ручной CRC8
uint8_t G433_crc_xor(uint8_t *buffer, uint8_t size);    // ручной CRC XOR
#define TRAINING_TIME_SLOW (500000UL)                   // время синхронизации для SLOW_MODE

// =========================================================================
#ifndef G433_SPEED
#define G433_SPEED 1000
#endif

// тайминги интерфейса
#define FRAME_TIME (1000000UL / G433_SPEED) // время фрейма (либо HIGH) 1000000/2000=500
#define HALF_FRAME (FRAME_TIME / 2)         // полфрейма (либо LOW) 500/2=250
#define START_PULSE (FRAME_TIME * 2)        // стартовый импульс 500*2=1000

// окно времени для обработки импульса
#define START_MIN (START_PULSE * 3 / 4)     //1000*3/4=750
#define START_MAX (START_PULSE * 5 / 4)     //1000*5/4=1250
#define FRAME_MIN (FRAME_TIME * 3 / 4)      //500*3/4=375
#define FRAME_MAX (FRAME_TIME * 5 / 4)      //500*5/4=625
#define HALF_FRAME_MIN (HALF_FRAME * 3 / 4) //250*3/4=187,5
#define HALF_FRAME_MAX (HALF_FRAME * 5 / 4) //250*5/4=312,5

// жоский delay для avr
#ifdef AVR
#define G433_DELAY _delay_us
// #else
// #define G433_DELAY delayMicroseconds0
#endif

// режимы CRC
#define G433_NOCRC 0
#define G433_CRC8 1
#define G433_XOR 2

// количество синхроимпульсов
#if defined(G433_FAST)
#define TRAINING_PULSES 10
#elif defined(G433_MEDIUM)
#define TRAINING_PULSES 50
#elif defined(G433_SLOW)
#define TRAINING_PULSES (TRAINING_TIME_SLOW / FRAME_TIME / 2)
#else
#define TRAINING_PULSES 50
#endif

//extern volatile unsigned long millis, micros; 

// crc8 один байт
void G433_crc8_byte(uint8_t &crc, uint8_t data); 

// ============  ============
template <uint8_t TX_PIN, uint16_t TX_BUF = 64, uint8_t CRC_MODE = G433_CRC8>
class Gyver433_TX {
    
public:
    // отправка, блокирующая. Кушает любой тип данных
    template <typename T>
    bool sendData(T &data) {
        if (sizeof(T) > TX_BUF) return 0;
        const uint8_t *ptr = (const uint8_t*) &data;
        for (uint16_t i = 0; i < sizeof(T); i++) buffer[i] = *ptr++;
        if (CRC_MODE == G433_CRC8) {
            buffer[sizeof(T)] = G433_crc8(buffer, sizeof(T));
            write(buffer, sizeof(T) + 1);
        } else if (CRC_MODE == G433_XOR) {
            buffer[sizeof(T)] = G433_crc_xor(buffer, sizeof(T));
            write(buffer, sizeof(T) + 1);
        } else {
            write(buffer, sizeof(T));
        }
        return 1;
    }
    
    // отправка сырого набора байтов
    void write(uint8_t* buf, uint16_t size) {
        for (uint16_t i = 0; i < TRAINING_PULSES; i++) {
            fastWrite(TX_PIN, 1);
            G433_DELAY(FRAME_TIME);
            fastWrite(TX_PIN, 0);
            G433_DELAY(FRAME_TIME);
        }
        fastWrite(TX_PIN, 1);       // старт
        G433_DELAY(START_PULSE);    // ждём
        fastWrite(TX_PIN, 0);       // старт бит
        
        #ifdef G433_MANCHESTER
        G433_DELAY(HALF_FRAME);       // ждём
        for (uint16_t n = 0; n < size; n++) {
            uint8_t data = buf[n];
            for (uint8_t b = 0; b < 8; b++) {
                fastWrite(TX_PIN, !(data & 1));
                G433_DELAY(HALF_FRAME);
                fastWrite(TX_PIN, (data & 1));                
                G433_DELAY(HALF_FRAME);
                data >>= 1;
            }
        }
        fastWrite(TX_PIN, 0);   // конец передачи
        #else
        bool flag = 0;
        for (uint16_t n = 0; n < size; n++) {
            uint8_t data = buf[n];
            for (uint8_t b = 0; b < 8; b++) {
                if (data & 1) G433_DELAY(FRAME_TIME);
                else G433_DELAY(HALF_FRAME);
                fastWrite(TX_PIN, flag = !flag);
                data >>= 1;
            }
        }
        #endif        
    }
    
    // доступ к буферу
    uint8_t buffer[TX_BUF + !!CRC_MODE];
    
private: 
   
};

// ===== CRC =====
void G433_crc8_byte(uint8_t &crc, uint8_t data) {
#if defined (__AVR__)
    // резкий алгоритм для AVR
    uint8_t counter;
    uint8_t buffer;
    asm volatile (
    "EOR %[crc_out], %[data_in] \n\t"
    "LDI %[counter], 8          \n\t"
    "LDI %[buffer], 0x8C        \n\t"
    "_loop_start_%=:            \n\t"
    "LSR %[crc_out]             \n\t"
    "BRCC _loop_end_%=          \n\t"
    "EOR %[crc_out], %[buffer]  \n\t"
    "_loop_end_%=:              \n\t"
    "DEC %[counter]             \n\t"
    "BRNE _loop_start_%="
    : [crc_out]"=r" (crc), [counter]"=d" (counter), [buffer]"=d" (buffer)
    : [crc_in]"0" (crc), [data_in]"r" (data)
    );
#else
    // обычный для всех остальных
    uint8_t i = 8;
    while (i--) {
        crc = ((crc ^ data) & 1) ? (crc >> 1) ^ 0x8C : (crc >> 1);
        data >>= 1;
    }
#endif
}

uint8_t G433_crc8(uint8_t *buffer, uint8_t size) {
    uint8_t crc = 0;
    for (uint8_t i = 0; i < size; i++) G433_crc8_byte(crc, buffer[i]);
    return crc;
}
uint8_t G433_crc_xor(uint8_t *buffer, uint8_t size) {
    uint8_t crc = 0;
    for (uint8_t i = 0; i < size; i++) crc ^= buffer[i];
    return crc;
}
#endif /*Gyver433_H_*/

После чего решил объявления оставить в .h, а основной код отправить в .cpp, и тогда FastIO у меня вообще проблем не возникло, а вот с Gyver433.cpp да, и проблема именно с шаблоном класса, когда объявляешь объект класса в основном файле main.cpp

Gyver433_TX <RADIO_DATA, RADIO_BUF_SIZE, G433_XOR> tx;

то лезет ошибка

Severity Code Description Project File Line
Error ‘Gyver433_TX’ does not name a type atmega8_433MHz G:\main.cpp 80

ну и основной код который отправил в .cpp

Gyver433.cpp
#include "Gyver433.h"
// ============ ПЕРЕДАТЧИК ============
template <uint8_t TX_PIN, uint16_t TX_BUF = 64, uint8_t CRC_MODE = G433_CRC8>

class Gyver433_TX {
	
	public:
	//     Gyver433_TX() {
	//         pinMode(TX_PIN, OUTPUT); // не нужно т.к. будеи обращатьс сразу напрямую через fastRead(),
	// 								   // просто пишем номер порта как в ардуино, далее fastRead() или fastWrite() сами разберутся
	//     }
	
	
	// отправка, блокирующая. Кушает любой тип данных
	template <typename T>
	bool sendData(T &data) {
		if (sizeof(T) > TX_BUF) return 0;
		const uint8_t *ptr = (const uint8_t*) &data;
		for (uint16_t i = 0; i < sizeof(T); i++) buffer[i] = *ptr++;
		if (CRC_MODE == G433_CRC8) {
			buffer[sizeof(T)] = G433_crc8(buffer, sizeof(T));
			write(buffer, sizeof(T) + 1);
			} else if (CRC_MODE == G433_XOR) {
			buffer[sizeof(T)] = G433_crc_xor(buffer, sizeof(T));
			write(buffer, sizeof(T) + 1);
			} else {
			write(buffer, sizeof(T));
		}
		return 1;
	}
	
	// отправка сырого набора байтов
	void write(uint8_t* buf, uint16_t size) {
		for (uint16_t i = 0; i < TRAINING_PULSES; i++) {
			fastWrite(TX_PIN, 1);
			G433_DELAY(FRAME_TIME);
			fastWrite(TX_PIN, 0);
			G433_DELAY(FRAME_TIME);
		}
		fastWrite(TX_PIN, 1);       // старт
		G433_DELAY(START_PULSE);    // ждём
		fastWrite(TX_PIN, 0);       // старт бит
		
		#ifdef G433_MANCHESTER
		G433_DELAY(HALF_FRAME);       // ждём
		for (uint16_t n = 0; n < size; n++) {
			uint8_t data = buf[n];
			for (uint8_t b = 0; b < 8; b++) {
				fastWrite(TX_PIN, !(data & 1));
				G433_DELAY(HALF_FRAME);
				fastWrite(TX_PIN, (data & 1));
				G433_DELAY(HALF_FRAME);
				data >>= 1;
			}
		}
		fastWrite(TX_PIN, 0);   // конец передачи
		#else
		bool flag = 0;
		for (uint16_t n = 0; n < size; n++) {
			uint8_t data = buf[n];
			for (uint8_t b = 0; b < 8; b++) {
				if (data & 1) G433_DELAY(FRAME_TIME);
				else G433_DELAY(HALF_FRAME);
				fastWrite(TX_PIN, flag = !flag);
				data >>= 1;
			}
		}
		#endif
	}
	
	// доступ к буферу
	uint8_t buffer[TX_BUF + !!CRC_MODE];
	
	private:
	
};

// ===== CRC =====
void G433_crc8_byte(uint8_t &crc, uint8_t data) {
	#if defined (__AVR__)
	// резкий алгоритм для AVR
	uint8_t counter;
	uint8_t buffer;
	asm volatile (
	"EOR %[crc_out], %[data_in] \n\t"
	"LDI %[counter], 8          \n\t"
	"LDI %[buffer], 0x8C        \n\t"
	"_loop_start_%=:            \n\t"
	"LSR %[crc_out]             \n\t"
	"BRCC _loop_end_%=          \n\t"
	"EOR %[crc_out], %[buffer]  \n\t"
	"_loop_end_%=:              \n\t"
	"DEC %[counter]             \n\t"
	"BRNE _loop_start_%="
	: [crc_out]"=r" (crc), [counter]"=d" (counter), [buffer]"=d" (buffer)
	: [crc_in]"0" (crc), [data_in]"r" (data)
	);
	#else
	// обычный для всех остальных
	uint8_t i = 8;
	while (i--) {
		crc = ((crc ^ data) & 1) ? (crc >> 1) ^ 0x8C : (crc >> 1);
		data >>= 1;
	}
	#endif
}

uint8_t G433_crc8(uint8_t *buffer, uint8_t size) {
	uint8_t crc = 0;
	for (uint8_t i = 0; i < size; i++) G433_crc8_byte(crc, buffer[i]);
	return crc;
}
uint8_t G433_crc_xor(uint8_t *buffer, uint8_t size) {
	uint8_t crc = 0;
	for (uint8_t i = 0; i < size; i++) crc ^= buffer[i];
	return crc;
}

Суть вопроса что не так делаю с объектом класса, связано как с тем что объявляю в другом файле main, почему выдает ошибку не указан тип. Хотя сам объект класса Gyver_433 мне сам компилятор подсказывает ввести.

Попытаться всунуть ардуиновскую библиотеку в студию и удивляться, что она не работает? Да вы знаете толк в извращениях

Опять огрызки кода какие-то.

а по существу заданного вопроса? я не огрызки вывел и полностью файлы

какая разница где писать я пишу на в студии, и работаю на прямую с регистрами, убираю лишнее… вопрос то читали, меня интересует что объектом класса не так? или для этого тоже нужна дуняиде?

Обьявление и определение шаблона нельзя разделять на два файла, как обычные функции и методы.Верните обратно.
Самое простое решение вашей проблемы - переделать вашу программу так, чтобы методы либы Gyver433.h использовались только в одном модуле компиляции, попросту говоря, только в одном файле.

1 лайк

Если вы работаете напрямую с регистрами и т.д. и т.п., то при чем здесь ардуиновские библиотеки? Пишите свой код и не парьте людям моск. В крайнем случае обратитесь к авторам библиотек. Уж про гайверовские библиотеки вы здесь точно сочувствия не найдете

Да? А это что?

Не вижу этого файла, ни полностью, ни как-то еще. Давай ты не будешь пытаться навесить лапшу на уши опытным людям, раз уж пришел за помощью.

да он был в одном файле .h, но лезут другие те ошибки от которых я уходил(описал в самом начале), поэтому раскидал все на .h и .cpp

И что получилось? Как именно Вы это сделали? Этого кода нет. Ведь не работает именно это! А вот именно этого (того, что не работает) Вы нам и не показали.

Давайте так, забудьте про эту кучу кодов, показывайте те файлы, которые не работают и то, как Вы их вставили в проект в Студии.

Из общих соображений - объявление класса должно быть доступно везде, где класс используется. Также, на всякий случай, слово “library” в “Студии” означает совсем не то, что в ИДЕ.

а ну понятна в чем причина, вы гайверу моз выносите с нелюбовью, я то тут причем, написал бы просто без гайвера, че б тогда… какие аргументы были?))

лезут ошибки многократного определения, потому что вы включили Gyver433.h более чем один раз.
Еще раз прочитайте что я пишу и постарайтесь вникнуть - вам надо переписать программу так, чтобы либа использовалась только в одном файле .cpp

1 лайк

А вот хамить не надо. Вас попросили привести код, приведите. А будете заниматься психоанализом, пойдёте на … гиверовский форум.

Gyver433.h
#ifndef Gyver433_H_
#define Gyver433_H_

#include "main.h"
#include "FastIO.h"


uint8_t G433_crc8(uint8_t *buffer, uint8_t size);       // ручной CRC8
uint8_t G433_crc_xor(uint8_t *buffer, uint8_t size);    // ручной CRC XOR
#define TRAINING_TIME_SLOW (500000UL)                   // время синхронизации для SLOW_MODE

// =========================================================================
#ifndef G433_SPEED
#define G433_SPEED 1000
#endif

// тайминги интерфейса
#define FRAME_TIME (1000000UL / G433_SPEED) // время фрейма (либо HIGH) 1000000/2000=500
#define HALF_FRAME (FRAME_TIME / 2)         // полфрейма (либо LOW) 500/2=250
#define START_PULSE (FRAME_TIME * 2)        // стартовый импульс 500*2=1000

// окно времени для обработки импульса
#define START_MIN (START_PULSE * 3 / 4) 	//1000*3/4=750
#define START_MAX (START_PULSE * 5 / 4) 	//1000*5/4=1250
#define FRAME_MIN (FRAME_TIME * 3 / 4) 		//500*3/4=375
#define FRAME_MAX (FRAME_TIME * 5 / 4) 		//500*5/4=625
#define HALF_FRAME_MIN (HALF_FRAME * 3 / 4) //250*3/4=187,5
#define HALF_FRAME_MAX (HALF_FRAME * 5 / 4) //250*5/4=312,5

// жоский delay для avr
#ifdef AVR
#define G433_DELAY _delay_us
#else
#define G433_DELAY delayMicroseconds0
#endif

// режимы CRC
#define G433_NOCRC 0
#define G433_CRC8 1
#define G433_XOR 2

// количество синхроимпульсов
#if defined(G433_FAST)
#define TRAINING_PULSES 10
#elif defined(G433_MEDIUM)
#define TRAINING_PULSES 50
#elif defined(G433_SLOW)
#define TRAINING_PULSES (TRAINING_TIME_SLOW / FRAME_TIME / 2)
#else
#define TRAINING_PULSES 50
#endif

// crc8 один байт
void G433_crc8_byte(uint8_t &crc, uint8_t data); 

#endif /*Gyver433_H_*/
Gyver433.cpp
#include "Gyver433.h"

// ============ ПЕРЕДАТЧИК ============
template <uint8_t TX_PIN, uint16_t TX_BUF = 64, uint8_t CRC_MODE = G433_CRC8>

class Gyver433_TX {
	
	public:
	//     Gyver433_TX() {
	//         pinMode(TX_PIN, OUTPUT); // не нужно т.к. будеи обращатьс сразу напрямую через fastRead(),
	// 								   // просто пишем номер порта как в ардуино, далее fastRead() или fastWrite() сами разберутся
	//     }
	
	
	// отправка, блокирующая. Кушает любой тип данных
	template <typename T>
	bool sendData(T &data) {
		if (sizeof(T) > TX_BUF) return 0;
		const uint8_t *ptr = (const uint8_t*) &data;
		for (uint16_t i = 0; i < sizeof(T); i++) buffer[i] = *ptr++;
		if (CRC_MODE == G433_CRC8) {
			buffer[sizeof(T)] = G433_crc8(buffer, sizeof(T));
			write(buffer, sizeof(T) + 1);
			} else if (CRC_MODE == G433_XOR) {
			buffer[sizeof(T)] = G433_crc_xor(buffer, sizeof(T));
			write(buffer, sizeof(T) + 1);
			} else {
			write(buffer, sizeof(T));
		}
		return 1;
	}
	
	// отправка сырого набора байтов
	void write(uint8_t* buf, uint16_t size) {
		for (uint16_t i = 0; i < TRAINING_PULSES; i++) {
			fastWrite(TX_PIN, 1);
			G433_DELAY(FRAME_TIME);
			fastWrite(TX_PIN, 0);
			G433_DELAY(FRAME_TIME);
		}
		fastWrite(TX_PIN, 1);       // старт
		G433_DELAY(START_PULSE);    // ждём
		fastWrite(TX_PIN, 0);       // старт бит
		
		#ifdef G433_MANCHESTER
		G433_DELAY(HALF_FRAME);       // ждём
		for (uint16_t n = 0; n < size; n++) {
			uint8_t data = buf[n];
			for (uint8_t b = 0; b < 8; b++) {
				fastWrite(TX_PIN, !(data & 1));
				G433_DELAY(HALF_FRAME);
				fastWrite(TX_PIN, (data & 1));
				G433_DELAY(HALF_FRAME);
				data >>= 1;
			}
		}
		fastWrite(TX_PIN, 0);   // конец передачи
		#else
		bool flag = 0;
		for (uint16_t n = 0; n < size; n++) {
			uint8_t data = buf[n];
			for (uint8_t b = 0; b < 8; b++) {
				if (data & 1) G433_DELAY(FRAME_TIME);
				else G433_DELAY(HALF_FRAME);
				fastWrite(TX_PIN, flag = !flag);
				data >>= 1;
			}
		}
		#endif
	}
	
	// доступ к буферу
	uint8_t buffer[TX_BUF + !!CRC_MODE];
	
	private:
	
};

// ===== CRC =====
void G433_crc8_byte(uint8_t &crc, uint8_t data) {
	#if defined (__AVR__)
	// резкий алгоритм для AVR
	uint8_t counter;
	uint8_t buffer;
	asm volatile (
	"EOR %[crc_out], %[data_in] \n\t"
	"LDI %[counter], 8          \n\t"
	"LDI %[buffer], 0x8C        \n\t"
	"_loop_start_%=:            \n\t"
	"LSR %[crc_out]             \n\t"
	"BRCC _loop_end_%=          \n\t"
	"EOR %[crc_out], %[buffer]  \n\t"
	"_loop_end_%=:              \n\t"
	"DEC %[counter]             \n\t"
	"BRNE _loop_start_%="
	: [crc_out]"=r" (crc), [counter]"=d" (counter), [buffer]"=d" (buffer)
	: [crc_in]"0" (crc), [data_in]"r" (data)
	);
	#else
	// обычный для всех остальных
	uint8_t i = 8;
	while (i--) {
		crc = ((crc ^ data) & 1) ? (crc >> 1) ^ 0x8C : (crc >> 1);
		data >>= 1;
	}
	#endif
}

uint8_t G433_crc8(uint8_t *buffer, uint8_t size) {
	uint8_t crc = 0;
	for (uint8_t i = 0; i < size; i++) G433_crc8_byte(crc, buffer[i]);
	return crc;
}
uint8_t G433_crc_xor(uint8_t *buffer, uint8_t size) {
	uint8_t crc = 0;
	for (uint8_t i = 0; i < size; i++) crc ^= buffer[i];
	return crc;
}
main.h
#ifndef MAIN_H_
#define MAIN_H_

#define XTAL 8000000UL

#define SREG _SFR_IO8(0x3F)

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdbool.h>  
#include <stdint.h>

#include "Gyver433.h"

#endif /* MAIN_H_ */
main.cpp
#include "main.h"

#define RADIO_DATA 15  
#define RADIO_BUF_SIZE 10
#define G433_SPEED 1000

Gyver433_TX <RADIO_DATA, RADIO_BUF_SIZE, G433_XOR> tx;

int main(void)
{
        while(1){

         }
}

ну думаю я вам все дал теперь!

кому я в чем нахамил?

да я так тоже думал, что более чем один раз… я попробую переделать учитывая ваше мнение!

Ты не просто хамишь, ты издеваешься уже. Где 80я строка, в которой у тебя ошибка? Где int main()?
В общем можешь не напрягаться уже. Тест на идиота провален с треском.

Какая-то маниакальная потребность у гайвера - заменить все библиотеки в мире своими поделиями…

1 лайк

вот она!
когда объявляешь объект класса в основном файле main.cpp

Gyver433_TX <RADIO_DATA, RADIO_BUF_SIZE, G433_XOR> tx;

или вот тут 13 ответ для ЕвгенийП

У меня, как обычно, чисто энтомологический интерес: а зачем ты в giver.h включаешь
main.h?
Ух ты! Но при этом в main.cpp не включен giver.h! ??WTF??