Вывести тип typedef во время компиляции в C ++ (особенно при возникновении ошибки) - PullRequest
5 голосов
/ 22 января 2012

Мне очень сложно объяснить эту конкретную проблему / вопрос, поэтому, пожалуйста, потерпите меня (у меня проблемы со всеми вопросами, связанными с моим шаблоном!).

Взять этот код в качестве примера (обратите внимание, что смысл показа кода - показать сложную иерархию шаблонов, а не то, имеет ли это смысл):

#include <string>
#include <vector>
#include <list>

template <typename T>
struct Foo
{
  typedef typename T::value_type value_type;
  typedef typename T::value_type1 value_type1;
  typedef typename T::value_type2 value_type2;

  Foo() {}
  Foo(value_type1, value_type, value_type2) {}
  Foo(value_type, value_type1, value_type2) {}
};

template <typename T, typename T1, typename T2>
struct MiddleMan
{
  typedef T   value_type;
  typedef T1  value_type1;
  typedef T2  value_type2;
};

template <typename T>
struct MainClass
{
  typedef typename T::value_type value_type;
  typedef typename T::value_type1 value_type1;
  typedef typename T::value_type2 value_type2;

  typedef MainClass<T>  this_type;

  typedef Foo<this_type> iterator;
};

using namespace std;

int main()
{
  typedef MiddleMan<string, vector<string>, list<vector<string> > > mm;
  MainClass<mm>::iterator  a(1, 2, 3);

  return 0;
}

и предположим, что это ошибка, которую вы получаете

Ни одна из трех перегрузок не может преобразовать все типы аргументов

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

Теперь я хочу знать типы Foo, то есть value_type, value_type1, value_type2, чтобы я мог исправить ошибку, не возвращаясь обратно к MiddleMan. Причина, по которой я не хочу выполнять трассировку вручную, состоит в том, что код может быть довольно сложным шаблоном кода, где выполнить трассировку очень сложно.

Я понял, поскольку компилятор уже определил типы, он должен дать мне знать, то есть должен быть простой способ выяснить это во время компиляции (возможно, с помощью сообщения в окне вывода) типов прикреплен к typedef с. Есть ли простой способ?


РЕШЕНИЕ-РЕДАКТИРОВАНИЕ: Вот еще один пример, который может помочь будущему SOER после прочтения выбранного ответа:

template <typename T> struct incomplete;

template <typename T, typename T2, typename T3>
class foo
{
public:
  typedef T value_type;
  typedef T2 value_type2;
  typedef T3 value_type3;
};

int main()
{
  // Assume the following type is much more complex
  typedef foo<float, int, char> type_i_am_having_trouble_with;

  // At this point you are instantiating it, and the program compiles (or maybe
  // not) and you have no idea what some of the typedefs stand for
  type_i_am_having_trouble_with b;

  // Use this to find out what the typedefs stand for
  incomplete<type_i_am_having_trouble_with::value_type> test; 
}

Вывод из Visual C ++ 2008:

error C2079: 'test' uses undefined struct 'incomplete<T>'
1>        with
1>        [
1>            T=float
1>        ]

1 Ответ

7 голосов
/ 22 января 2012

Есть несколько хитростей, чтобы компилятор показал вам фактический тип typedef. Один из них - попытаться создать экземпляр неполного типа.

template<typename>
struct Printer;

typedef std::vector<int> foobartype;
Printer<foobartype> printer;

Существует также boost :: mpl :: print , который может выдавать предупреждение вместо сбоя.

Все эти методы должны использоваться в том месте, где имя типа действительно доступно, поэтому вам в конечном итоге придется «проследить» через код.

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

...