Ошибка неполного типа в BGL при использовании связанных свойств

У меня этот код правильно компилировался в какой-то версии g++ 4.x, теперь версия 4.6 завершает компиляцию с ошибкой:

/usr/include/boost/pending/property.hpp:35:7: error: ‘boost::property<Tag, T, Base>::m_value’ has incomplete type

Ошибка, по-видимому, вызвана циклом между объявлениями типа graph_type и edge_info.

Я смог изолировать проблему в следующих нескольких строках кода. Как я могу использовать тип, зависящий от связанного свойства узлов, для определения свойства ребер? Решение по-прежнему должно использовать связанные свойства (поскольку большая часть кода зависит от этого типа графа). Как я могу исправить следующий код?

#include <iostream>
#include <boost/graph/adjacency_list.hpp>

using namespace std;
using namespace boost;

template<typename map_type>
struct map_computation {
  map_type m;
};

struct vertex_info;
struct edge_info;

typedef adjacency_list<vecS, 
               vecS, 
               bidirectionalS, 
               vertex_info, 
               edge_info> graph_type;

struct position {
  double x, y;
};

struct vertex_info {
  position p;
};

typedef boost::property_map<graph_type, 
                position vertex_info::*>::type position_map_type;

struct edge_info {
  map_computation<position_map_type>* c;
};

int main(int argc, char* argv[])
{
  graph_type g;
  return 0;
}

РЕДАКТИРОВАТЬ: полный журнал ошибок гласит:

In file included from /usr/include/boost/graph/graph_traits.hpp:22:0,
                 from /usr/include/boost/graph/adjacency_list.hpp:33,
                 from gtest.cc:2:
/usr/include/boost/pending/property.hpp: In instantiation of ‘boost::property<boost::edge_bundle_t, edge_info, boost::no_property>’:
/usr/include/boost/pending/detail/property.hpp:94:48:   instantiated from ‘boost::detail::build_property_tag_value_alist<boost::property<boost::edge_bundle_t, edge_info, boost::no_property> >’
/usr/include/boost/pending/property.hpp:63:81:   instantiated from ‘boost::property_value<boost::property<boost::edge_bundle_t, edge_info, boost::no_property>, boost::edge_bundle_t>’
/usr/include/boost/graph/properties.hpp:448:63:   instantiated from ‘boost::graph_detail::retagged_bundle<boost::property<boost::edge_bundle_t, edge_info, boost::no_property>, boost::edge_bundle_t>’
/usr/include/boost/graph/properties.hpp:461:64:   instantiated from ‘boost::graph_detail::normal_property<edge_info, boost::edge_bundle_t>’
/usr/include/boost/graph/properties.hpp:473:12:   instantiated from ‘boost::graph_detail::edge_prop<edge_info>’
/usr/include/boost/graph/adjacency_list.hpp:381:70:   instantiated from ‘boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, vertex_info, edge_info>’
/usr/include/boost/graph/properties.hpp:418:44:   instantiated from ‘boost::property_map<boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, vertex_info, edge_info>, position vertex_info::*>’
gtest.cc:30:32:   instantiated from here
/usr/include/boost/pending/property.hpp:35:7: error: ‘boost::property<Tag, T, Base>::m_value’ has incomplete type
gtest.cc:13:8: error: forward declaration of ‘struct edge_info’
gtest.cc:33:45: error: template argument 1 is invalid

person baol    schedule 10.06.2012    source источник
comment
ошибка говорит with Tag = ..., T = ..., Base = ...?   -  person K-ballo    schedule 10.06.2012
comment
@K-ballo Я включил полный отчет об ошибке в тело вопроса. Спасибо.   -  person baol    schedule 14.06.2012


Ответы (1)


Вы не можете иметь определение рекурсивного типа, например

struct edge_info;

typedef adjacency_list<..., edge_info> graph_type;

typedef boost::property_map<graph_type, ...>::type position_map_type;

struct edge_info { map_computation<position_map_type>* c; };

Как упоминалось, например, в этот вопрос, в стандарте C++ говорится в §17.4.3.6/2,

В частности, эффекты не определены в следующих случаях:

__[..] — если неполный тип (3.9) используется в качестве аргумента шаблона при создании экземпляра компонента шаблона. __ [..]

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

template<typename edge>
class some_graph_type 
{ // ... };

class my_edge_type
: 
    public some_graph_type<my_edge_type> 
{ // ... };

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

person TemplateRex    schedule 11.06.2012
comment
Спасибо, я подумал, что ошибка моя, а не компилятора. Тем не менее, я хотел бы устранить ошибку компиляции с минимальными изменениями в коде, использующем graph_type. (кстати: я не могу изменить тип boost::graph (это тип повышения), поэтому я не понимаю, как CRTP может помочь в моем случае, пожалуйста, объясните. - person baol; 14.06.2012
comment
@baol Как я объяснил, если бы у вас был только edge* в качестве типа члена, это сработало бы. Но нет, если у вас есть указатель члена с edge в качестве параметра шаблона. - person TemplateRex; 14.06.2012
comment
@baol Вы только что отозвали статус «Принято»? Пожалуйста, дайте мне знать, как можно улучшить ответ. - person TemplateRex; 30.08.2013
comment
@TemplateTex вы очень подробно описали проблему, но не предложили решение. Если вам нужно больше контекста, обратитесь к документации библиотеки графов повышения. - person baol; 23.09.2013