int i;
А во втором:
extern int i;
Я сделал одну такую переменную, допустим var. После этого проект перестал собираться. Компоновщик (MSVS 2015) сообщал, что в одном из модулей уже есть такая переменная. Она действительно была, но внутри класса, поэтому не должна была мешать. Я даже включил отдельную работу препроцессора -- но в файле после препроцессора никаких дополнительных об'явлений var не обнаружил.
Я переименовал переменную. Теперь это была не var, а var2. После этого сообщение об ошибке изменилось. Компоновщик стал опять говорить, что теперь переменная var2 в модуле уже есть. Но на этот раз её не было даже в составе класса. Это было совершенно непонятно, и я загуглил. Гугл предлагал проверить, что типы обычного и erxtern об'явления совпадают. Они заведомо совпадали, т.к. extern об'явления я делаю копипастом, но я решил проверить, как я на самом деле написал об'явления и сравнить их побуквенно. И вот что я обнаружил:
float var2=1.0f;
extern float var2=1.0f;
Копипаст меня и подвёл. Да, дело было в инициализации. extern либо не умеет инициализировать переменные, либо плохо относится к инициализации в нескольких модулях сразу. Я убрал инициализацию из extern-об'явления -- и всё прекрасно собралось.
Таким образом, сообщение об ошибке компоновщика не отражало реальности.