#include <stdio.h>

// эти структуры заводят внутри компилятора новые типы, которые не совместимы с 
// другими типами, а главное - друг с другом
struct meters {
	int meter;
};

struct centimeters {
	int centimeter;
};

// это плохая функция, потому что в ней нет никакой информации о типах, и очень 
// сложно сказать есть ли в ней какая-нибудь ошибка
// конечно, в реальности она будет принимать int m, int cm, но это всё равно 
// довольно сложно заметить
int add_distances_bad( int a, int b ) {
	return a + b;
}

struct centimeters add_distances_good( struct meters a, struct centimeters b ) {
	// return a + b; // вот это просто не скомпилируется, потому что со
	// структурами так делать нельзя
	
	// это всё ещё неправильно, но такой код написать сложнее, и если он-таки
	// написан, то при прочтении легко заметить, что что-то тут не так, ибо 
	// метры складываются с сантиметрами
	//получается эдакий гибрид фантомных типов с венгерской нотацией, которая
	// кое-как проверяется компилятором
	return (struct centimeters) { a.meter + b.centimeter };
}

struct meters mk_meters( int a ) {
	return (struct meters){ a };
}

struct centimeters mk_centimeters( int a ) {
	return (struct centimeters){ a };
}
/*
	Сами структуры исчезнут после компиляции, даже если оптимизация выключена. 
	С -О3 от них не останется и следа.
	Потому что "механически" они полностью эквивалентны обычному инту.
*/
int main(void) {
	struct meters m = mk_meters( 10 );
	struct centimeters cm = mk_centimeters( 55 );
	struct centimeters result1 = add_distances_good( m, cm );
	int result2 = add_distances_bad( 10, 55 );
	printf( "distances are %d and %d\n", result1.centimeter, result2 );
	return 0;
}
