"Тип 'float' не требуется" и другие ошибки

C.h:

#pragma once

#include "Utils.h"

class C
{
public:
	C();
};

C.cpp

#include "C.h"

C::C()
{
}

F.h

#pragma once

class F
{
public:
	F();
};

F.cpp

#include "F.h"

F::F()
{
}

Utils.h

#pragma once

#include "C.h"
#include "F.h"

bool isSomething(C* c, F* f, float someFloat);

Utils.cpp

#include "Utils.h"

bool isSomething(C* c, F* f, float someFloat)
{
	return false;
}

Main.cpp

#include "C.h"
#include "F.h"
#include "Utils.h"

int main()
{
	return 0;
}

При компиляции выдаёт ошибки:

Пробовал менять местами инклюды - не помогает. Ошибок становится либо больше, либо меньше. Помогает только добавление строчек

class C;
class F;

в файле Utils.h сразу после инклюдов.
То что ошибка Тип 'float' не требуется выглядит очень нелепо - спишем на особенности языка и его компилятора. Он не редко выдаёт странные ошибки.
Я что хочу спросить - это нормальное решение? Или можно как-то вообще избежать этих ошибок (не избавляясь, при этом, от файла Utils)?

А зачем #include "Utils.h" в C.h?

Скорее перевод странный, в оригинале unexpected. Compiler Error C2062 | Microsoft Learn
Обычно такое происходит (в разных языках) когда что-то странное перед этим.

Здесь не за чем. Это пример кода. А в реальном проекте - нужен. Методы класса C им пользуются.

Методы класса C им пользуются.

Подключай его в .cpp-файл, а не в .h файл тогда. Методы же там, в .cpp-файле?

Я считаю, что проблема в том, что ты поленился разбираться, как работает #pragma once. Это нормально, я тоже когда-то разобрался, но уже забыл.

Да.

Да, точно. Так тестовый проект собрался. А реальный не собирается. Ошибки уже немного другие. Похоже, что методы класса C не видят одно из своих приватных полей (или как они в C++ называются). Глобальная private переменная класса, короче.
И ещё, из Main.cpp не получается вызвать функцию isSomething(...). Вижуалка её подчёркивает и говорит, что она дважды объявлена. Хотя #pragma once прописано во всех .h-файлах :man_shrugging:

Разве это не просто аналог include guard’ов для новых версий компиляторов? :thinking: С чем именно там необходимо разбираться? Да, я знаю, что кроме once там ещё есть куча параметров. С ними я, и правда, не разбирался. Но once это ведь пришло именно как замена инклюд-гардов, разве нет? :thinking:
Вот сейчас в проекте (который не-тест) в файле Utils.h заменил прагму на инклюд-гарды и ничего. Всё-равно не компилируется.
Только тут файлы и классы по-другому называются. Но их структуру в тесте я, вроде, правильно повторил :thinking:
Надо попробовать добавить в тест больше классов и смотреть, когда он перестанет собираться.

А, всё, понял. Это потому что я ещё одну библиотеку забыл заинклюдить. Она была заинклюжена в Utils.h, инклюд которого перенесли в .cpp.
Теперь компилируется.
Но, я так понял, что если в C.h будет фигурировать, скажем, класс W (например, в поле или параметрах какого-то метода), то всё-равно придётся написать в него (в C.h) строчку class W;? :thinking: