Как избежать typedef? - PullRequest
       8

Как избежать typedef?

0 голосов
/ 12 декабря 2010
template <class VertexType>
class GraphMatrix
{
};

template <class GraphType>
class Graph
{
 typedef typename GraphType::VertexType VertexType;
 GraphType* graph_;
 void addVertex(VertexType vertex)
 {
 }
 //...
};
int main()
{
    Graph <GraphMatrix <int> > graph;
    return 0;
}

Посмотрите, добавлю ли я строку typedef VertexType VertexType;//A к GraphMatrix class, этот код пройдет компиляцию и будет работать, иначе он выдаст ошибку компиляции.Ошибка: C2039: «VertexType»: не является членом «GraphMatrix».Мой вопрос заключается в следующем: «Есть ли способ (синтаксис) заставить вышеуказанный код работать без добавления этой глупой строки //A»?

Ответы [ 4 ]

1 голос
/ 12 декабря 2010

Мой вопрос заключается в следующем: есть ли способ (синтаксис) заставить вышеуказанный код работать без добавления этой глупой строки // A

Я так не думаю.

Однако есть несколько проблем с вашим кодом.GraphType является зависимым именем и указывает, что GraphType::VertexType является типом, который необходимо добавить typename перед ним.

Однако, когда шаблон класса создается для GraphType = GraphMatrix <int> компилятору не удалось найти GraphMatrix <int>::VertexType, поэтому вы получаете еще одну ошибку.

Поэтому, чтобы исправить ошибки, измените определение GraphMatrix на

template <class TVertexType>
class GraphMatrix
{
    public:
    typedef TVertexType VertexType;    
};

или что-то подобное.

Полный рабочий код здесь

1 голос
/ 12 декабря 2010

Вы всегда можете написать полное имя VertexType, typedef - это просто ярлык для вас, который вводит это имя в область и позволяет писать более понятный код.

Итак, нет , в этом случае другого пути нет.

Однако при использовании наследования вы можете using BaseClass::something перенести его в scope .

0 голосов
/ 12 декабря 2010

Если вы хотите получить аргумент шаблонного класса, передаваемый параметром шаблона, вы должны ограничить допустимые типы для GraphType.Вы делаете это по специализации:

template <class GraphType>
class Graph;

template <template <class> class GraphType, class VertexType>
class Graph<GraphType<VertexType> >
{
  ... // use GraphType<VertexType> as your graph, VertexType as your vertex type
};

Вы можете даже создать вспомогательную структуру, которая будет распаковывать аргументы для вас :

template <class T> struct get_arg;

template <template <class> class Tpl, class Arg>
struct get_arg<Tpl<Arg> >
{
  typedef Arg type;
};

Обратите внимание, что этоРешение довольно негибкое - оно допускает только шаблоны с одним параметром в качестве аргументов для шаблона класса Graph (представьте, что бы вы сделали, если бы добавили параметр в шаблон GraphMatrix).Поэтому он обычно не используется.

Обычным решением является либо добавление typedefs к вашим классам (как вы делаете со своей «глупой линией»), либо, что еще лучше, использование классов черт и их специализация.

0 голосов
/ 12 декабря 2010

Сомневаюсь.

С точки зрения шаблона Graph, параметр шаблона GraphType - это просто имя типа (так что в данном случае, "класс").Таким образом, если Graph создается с GraphType = GraphMatrix<int>, то Graph не может даже проверить, получил ли он экземпляр шаблона или "обычный" класс.Следовательно, он не может получить доступ к параметрам своего шаблона - потому что GraphType даже не нужно иметь никаких параметров шаблона.

Введение typedef в GraphType обогащает каждый экземпляр шаблона GraphMatrix открытой информацией о точнойнаберите его экземпляр - это именно то, чего вы хотите достичь.

...