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

Попытка скомпилировать приведенный ниже код не удалась из-за «конфликтующего объявления». Почему я не могу определить заранее объявленный класс как этот?

Я сделал это, чтобы скрыть, что реализация использует определенную библиотеку. Хотя я признаю, что это на самом деле ничего не абстрагирует — вам все равно нужно знать, что реализация использует для правильного вызова — я все еще заинтересован в Зачем это не работает

Bar.cpp:

#include "Bar.hpp"#include "Foo.hpp"
using Foo = ns::Foo;

void Bar::foo(Foo f) {
}

Bar.hpp:

class Foo;

class Bar {
void foo(Foo f);
};

Foo.hpp:

namespace ns {

class Foo {
};
}

Чтобы было ясно, я хочу знать, почему нельзя определить ранее объявленный класс с помощью псевдонимов — другими словами, говоря «используйте это определение там, у которого другое имя»

1

Решение

Вы декларируете Foo дважды с конфликтующими типами. Во-первых, вы объявляете Foo в Bar.hpp как:

class Foo;

Впоследствии вы объявляете foo в Bar.cpp как:

using Foo = ns::Foo;

Вы не можете поместить прямое объявление таким образом, если вы определили в своем исходном файле псевдоним с тем же именем, потому что тогда вы объявляете два разных типа с одинаковым именем.

Исходя из вашего вопроса, я предполагаю, что вы хотите использовать Foo без его пространства имен в Bar.cpp. Решение заключается в следующем:

Bar.cpp

#include "Bar.hpp"#include "Foo.hpp"
using ns::Foo;

void Bar::foo(Foo f) {}

Bar.hpp

namespace ns
{
class Foo;
}

class Bar
{
void foo(ns::Foo f);
};

Foo.hpp

namespace ns
{
class Foo
{};
}
4

Другие решения

Потому что для того, чтобы Bar::Foo чтобы работать, класс Bar должен знать размер аргумента Foo еще до его объявления.
Вы могли бы сделать эту работу, объявив void foo(Foo* f);
Таким образом, вместо того, чтобы знать размер Foo, компилятор будет заботиться только о размере указателя.
Просто используйте, чтобы выбрать нужное пространство имен:

using namespace ns;
0