Пишу свою реализацию динамической типизации в C++, но хочу вынести реализации перегрузок в отдельный файл, но компиль жалуется, что нет реализации <<. Не могу понять в чём проблема. Помогите пожалуйста.
dynamic.h
```
#pragma once
#include <iostream>
#include <string>
namespace dim {
// обычный print
template<typename T>
void println(const T& value) {
std::cout << std::boolalpha << value << "\n";
}
template<typename T, typename... Args>
void println(const T& value, const Args&... args) {
std::cout << std::boolalpha << value;
println(args...);
}
}
class Dynamic {
public:
Dynamic() : type(VType::Null), int_value(0) {}
Dynamic(int value) : type(VType::Int), int_value(value) {}
Dynamic(double value) : type(VType::Float), float_value(value) {}
Dynamic(const char* value) : type(VType::String), string_value(value) {}
Dynamic(char value) : type(VType::Char), char_value(value) {}
Dynamic(bool value) : type(VType::Bool), bool_value(value) {}
Dynamic& operator=(const int& value) {
type = VType::Int;
int_value = value;
return *this;
}
Dynamic& operator=(const double& value) {
type = VType::Float;
float_value = value;
return *this;
}
Dynamic& operator=(const char* value) {
type = VType::String;
string_value = value;
return *this;
}
Dynamic& operator=(const char& value) {
type = VType::Char;
char_value = value;
return *this;
}
Dynamic& operator=(const bool& value) {
type = VType::Bool;
bool_value = value;
return *this;
}
private:
enum VType { Null, Int, Float, String, Char, Bool };
VType type;
int int_value;
double float_value;
const char* string_value;
char char_value;
bool bool_value;
friend std::ostream& operator<<(std::ostream& os, const Dynamic& dynamic);
friend bool operator<(const Dynamic& lhs, const Dynamic& rhs);
friend bool operator>(const Dynamic& lhs, const Dynamic& rhs);
friend bool operator==(const Dynamic& lhs, const Dynamic& rhs);
friend bool operator!=(const Dynamic& lhs, const Dynamic& rhs);
friend bool operator>=(const Dynamic& lhs, const Dynamic& rhs);
friend bool operator<=(const Dynamic& lhs, const Dynamic& rhs);
friend void operator++(Dynamic& varible);
friend void operator--(Dynamic& varible);
friend Dynamic operator+(const Dynamic& lhs, const Dynamic& rhs);
friend Dynamic operator-(const Dynamic& lhs, const Dynamic& rhs);
friend Dynamic operator/(const Dynamic& lhs, const Dynamic& rhs);
friend Dynamic operator*(const Dynamic& lhs, const Dynamic& rhs);
friend Dynamic operator%(const Dynamic& lhs, const Dynamic& rhs);
};
bool operator<(const Dynamic& lhs, const Dynamic& rhs) {
if (lhs.type == Dynamic::VType::Int && rhs.type == Dynamic::VType::Int) { return lhs.int_value < rhs.int_value; }
if (lhs.type == Dynamic::VType::Float && rhs.type == Dynamic::VType::Float) { return lhs.float_value < rhs.float_value; }
if (lhs.type == Dynamic::VType::Char && rhs.type == Dynamic::VType::Char) { return lhs.char_value < rhs.char_value; }
if (lhs.type == Dynamic::VType::String && rhs.type == Dynamic::VType::String) { return lhs.string_value < rhs.string_value; }
return false;
}
bool operator>(const Dynamic& lhs, const Dynamic& rhs) {
if (lhs.type == Dynamic::VType::Int && rhs.type == Dynamic::VType::Int) { return lhs.int_value > rhs.int_value; }
if (lhs.type == Dynamic::VType::Float && rhs.type == Dynamic::VType::Float) { return lhs.float_value > rhs.float_value; }
if (lhs.type == Dynamic::VType::Char && rhs.type == Dynamic::VType::Char) { return lhs.char_value > rhs.char_value; }
if (lhs.type == Dynamic::VType::String && rhs.type == Dynamic::VType::String) { return lhs.string_value > rhs.string_value; }
return false;
}
bool operator>=(const Dynamic& lhs, const Dynamic& rhs) {
if (lhs.type == Dynamic::VType::Int && rhs.type == Dynamic::VType::Int) { return lhs.int_value >= rhs.int_value; }
if (lhs.type == Dynamic::VType::Float && rhs.type == Dynamic::VType::Float) { return lhs.float_value >= rhs.float_value; }
if (lhs.type == Dynamic::VType::Char && rhs.type == Dynamic::VType::Char) { return lhs.char_value >= rhs.char_value; }
if (lhs.type == Dynamic::VType::String && rhs.type == Dynamic::VType::String) { return lhs.string_value >= rhs.string_value; }
return false;
}
bool operator<=(const Dynamic& lhs, const Dynamic& rhs) {
if (lhs.type == Dynamic::VType::Int && rhs.type == Dynamic::VType::Int) { return lhs.int_value <= rhs.int_value; }
if (lhs.type == Dynamic::VType::Float && rhs.type == Dynamic::VType::Float) { return lhs.float_value <= rhs.float_value; }
if (lhs.type == Dynamic::VType::Char && rhs.type == Dynamic::VType::Char) { return lhs.char_value <= rhs.char_value; }
if (lhs.type == Dynamic::VType::String && rhs.type == Dynamic::VType::String) { return lhs.string_value <= rhs.string_value; }
return false;
}
bool operator==(const Dynamic& lhs, const Dynamic& rhs) {
if (lhs.type == Dynamic::VType::Int && rhs.type == Dynamic::VType::Int) { return lhs.int_value == rhs.int_value; }
if (lhs.type == Dynamic::VType::Float && rhs.type == Dynamic::VType::Float) { return lhs.float_value == rhs.float_value; }
if (lhs.type == Dynamic::VType::Char && rhs.type == Dynamic::VType::Char) { return lhs.char_value == rhs.char_value; }
if (lhs.type == Dynamic::VType::String && rhs.type == Dynamic::VType::String) { return lhs.string_value == rhs.string_value; }
return false;
}
bool operator!=(const Dynamic& lhs, const Dynamic& rhs) {
if (lhs.type == Dynamic::VType::Int && rhs.type == Dynamic::VType::Int) { return lhs.int_value != rhs.int_value; }
if (lhs.type == Dynamic::VType::Float && rhs.type == Dynamic::VType::Float) { return lhs.float_value != rhs.float_value; }
if (lhs.type == Dynamic::VType::Char && rhs.type == Dynamic::VType::Char) { return lhs.char_value != rhs.char_value; }
if (lhs.type == Dynamic::VType::String && rhs.type == Dynamic::VType::String) { return lhs.string_value != rhs.string_value; }
return false;
}
void operator++(Dynamic& varible) {
if (varible.type == Dynamic::VType::Int) { ++varible.int_value; }
if (varible.type == Dynamic::VType::Float) { ++varible.float_value; }
}
void operator--(Dynamic& varible) {
if (varible.type == Dynamic::VType::Int) { --varible.int_value; }
if (varible.type == Dynamic::VType::Float) { --varible.float_value; }
}
Dynamic operator+(const Dynamic& lhs, const Dynamic& rhs){
if (lhs.type == Dynamic::VType::Int && rhs.type == Dynamic::VType::Int) { return lhs.int_value + rhs.int_value; }
if (lhs.type == Dynamic::VType::Float && rhs.type == Dynamic::VType::Float) { return lhs.float_value + rhs.float_value; }
if (lhs.type == Dynamic::VType::String && rhs.type == Dynamic::VType::String) {
char *s = new char[strlen(lhs.string_value)+strlen(rhs.string_value)+1];
std::strcpy(s, lhs.string_value);
std::strcat(s, rhs.string_value);
return s;
}
}
Dynamic operator-(const Dynamic& lhs, const Dynamic& rhs){
if (lhs.type == Dynamic::VType::Int && rhs.type == Dynamic::VType::Int) { return lhs.int_value - rhs.int_value; }
if (lhs.type == Dynamic::VType::Float && rhs.type == Dynamic::VType::Float) { return lhs.float_value - rhs.float_value; }
}
Dynamic operator/(const Dynamic& lhs, const Dynamic& rhs){
if (lhs.type == Dynamic::VType::Int && rhs.type == Dynamic::VType::Int) { return lhs.int_value / rhs.int_value; }
if (lhs.type == Dynamic::VType::Float && rhs.type == Dynamic::VType::Float) { return lhs.float_value / rhs.float_value; }
}
Dynamic operator*(const Dynamic& lhs, const Dynamic& rhs){
if (lhs.type == Dynamic::VType::Int && rhs.type == Dynamic::VType::Int) { return lhs.int_value * rhs.int_value; }
if (lhs.type == Dynamic::VType::Float && rhs.type == Dynamic::VType::Float) { return lhs.float_value * rhs.float_value; }
}
Dynamic operator%(c
onst Dynamic& lhs, const Dynamic& rhs){
if (lhs.type == Dynamic::VType::Int && rhs.type == Dynamic::VType::Int) { return lhs.int_value % rhs.int_value; }
}
```
dynamic.cpp
```
#include "dynamic.h"
std::ostream& Dynamic::operator<<(std::ostream& os, const Dynamic& dynamic) {
switch (dynamic.type) {
case Dynamic::VType::Int:
os << dynamic.int_value;
break;
case Dynamic::VType::Float:
os << dynamic.float_value;
break;
case Dynamic::VType::String:
os << dynamic.string_value;
break;
case Dynamic::VType::Char:
os << dynamic.char_value;
break;
case Dynamic::VType::Bool:
os << (dynamic.bool_value ? "true" : "false");
break;
default:
os << "Uncknown type " << dynamic.type;
break;
}
return os;
}
```
main.cpp
```
#include "dynamic.h"
int main() {
Dynamic a = "Hello ";
Dynamic b = "World";
dim::println(a+b);
return 0;
}
```