«используя typedef-name ... as class» в предварительном объявлении - PullRequest
6 голосов
/ 15 февраля 2010

Я делаю здесь несколько основанных на политике дизайнов, и мне нужно набрать много типов шаблонов, чтобы сократить имена.
Теперь возникает проблема: когда мне нужно использовать указатель на один из этих типов, я пытаюсь просто объявить его вперед, но компилятор жалуется с test.cpp:8: error: using typedef-name ‘Test1’ after ‘class’
Это не имеет ничего общего с размерами, так как мне вообще не нужен объект obj, это просто указатель в файле ".h", куда я не хочу вносить весь шаблон.
Это г ++:

//Works
class Test{};
class Test;

//Doesn't work
class Test{};
typedef Test Test1;
class Test1;

Есть подсказка?

Ответы [ 3 ]

16 голосов
/ 15 февраля 2010

Это верно. Имя typedef не может использоваться в таком прямом объявлении (это технически называется разработанным спецификатором типа, и если такой спецификатор преобразуется в typedef-name, программа плохо сформирована).

Я не понимаю, зачем вам на самом деле нужно предварительное объявление. Потому что, если у вас уже есть typedef, почему бы просто не использовать этот typedef? Это просто также обозначает этот класс.

Редактировать : Судя по вашему комментарию, вам нужен назначенный заголовок предварительной декларации, почти такой же, как <iosfwd>. Итак, если ваш шаблон называется Test_Template_Name_Long, этот заголовок может выглядеть как

TestFwd.h

template<typename A, typename B> 
class Test_Template_Name_Long;

typedef Test_Template_Name_Long<int, bool> Test1;

Тогда вы можете просто использовать этот заголовок вместо class Test1, который компилятор не знает, что это такое (и будет думать, что это новый класс, независимый от любого шаблона и typedef).

2 голосов
/ 07 мая 2012

Еще один случай, когда возникает такая ситуация:

// File: network_fwd.hpp
#ifndef __NETWORK_FWD_HPP__
#define __NETWORK_FWD_HPP__
class Network;
typedef Network GarnetNetwork;
#endif // __NETWORK_FWD_HPP__

// File: network.hpp
#include "network_fwd.hpp"

class GarnetIntLink : public BasicLink
{
  public:

    friend class GarnetNetwork;

};

Я должен был сделать это, потому что на самом деле был класс GarnetNetwork, который я объединил в класс Network, и я хотел распространить это на остальную часть кода, используя этот typedef. GCC по-прежнему выдает следующее сообщение: ошибка: использование typedef-имени ‘GarnetNetwork’ после ‘class’ .

Я очень ценю вашу помощь по этому делу.

NB: Кстати, я разместил этот вопрос здесь, потому что я думал, что это почти одно и то же, и чтобы не отвлекать сообщество.

2 голосов
/ 15 февраля 2010
typedef Test Test1;
class Test1;

терпит неудачу, потому что оператор typedef служит объявлением для типа Test1.

По сути, когда компилятор видит typedef, он вспоминает, что Test1 является синонимом Test. Затем, когда он видит class Test1;, он думает, что вы объявляете новый тип. Но это не может восприниматься как объявление, потому что имя Test1 уже используется typedef.

Если вы хотите использовать прямое объявление для Test1, например, вы должны поместить typedef в каждый файл, используя этот typedef в качестве прямого объявления. Поэтому вместо class Test1; вы должны сделать:

class Test;
typedef Test Test1;
...