2012-06-10 2 views
2

Я имел этот код компиляция правильно на некотором г ++ 4.x версий, теперь версия 4.6 завершает компиляцию с сообщением об ошибке:Неполной ошибки типа в BGL при использовании пакетных свойств

/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; 
} 

EDIT: полный журнал ошибок гласит:

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 
+0

делает ошибку: _with Tag = ..., T = ..., Base = ..._? –

+0

@ K-ballo Я включил полный отчет об ошибке в тело вопроса. Благодарю. – baol

ответ

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; }; 

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

In particular, the effects are undefined in the following cases:

__ [..] — if an incomplete type (3.9) is used as a template argument when instantiating a template component. __ [..]

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

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

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

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

+0

Спасибо, я представил себе, что ошибка была моей, а не компилятором. Тем не менее я хотел бы решить ошибку компиляции с минимальным изменением кода, использующего graph_type. (btw: я не могу изменить тип boost :: graph (это тип boost), поэтому я не понимаю, как CRTP может помочь в моем случае, пожалуйста, объясните. – baol

+0

btw: тип может быть неполным, но мне нужно только pointer! – baol

+0

@baol Как я уже говорил, если бы у вас был только «edge *» в качестве типа члена, это сработало бы. Но если у вас есть указатель на члену с параметром «edge» в качестве параметра шаблона. – TemplateRex