4

I need to create a generic class containing multiindex container as a storage. when I compile, it gives error as below where I have defined nth index view.

error: non-template ‘nth_index’ used as template


/**
 * connection manager
 */

template < typename T, typename C > class conn_mgr: boost::noncopyable { public: /** * connection ptr */ typedef boost::shared_ptr conn_ptr_t;
/** * connection table type * It's a multi index container */ typedef boost::multi_index::multi_index_container < conn_ptr_t, boost::multi_index::indexed_by < //sequenced < >, boost::multi_index::hashed_unique < BOOST_MULTI_INDEX_CONST_MEM_FUN(T, std::string, T::id) >, boost::multi_index::hashed_non_unique < BOOST_MULTI_INDEX_CONST_MEM_FUN(T, std::string, T::type)>, boost::multi_index::hashed_non_unique < boost::multi_index::composite_key < conn_ptr_t, BOOST_MULTI_INDEX_CONST_MEM_FUN(T, std::string, T::id), BOOST_MULTI_INDEX_CONST_MEM_FUN(T, std::string, T::type ) > > > > conn_table_t;

//typedef for ConnectionIdView
typedef conn_table_t::nth_index<0>::type conn_table_by_id_type;

typedef conn_table_t::nth_index<1>::type conn_table_by_type;

typedef conn_table_t::nth_index<2>::type conn_table_by_id_type;

private: conn_table_t conn_table_; };


and here how I am using in main.

int main( int argc, char** argv ) { typedef conn_mgr < smpp_conn, smpp_config > smpp_conn_mgr_t; smpp_conn_mgr_t conn_mgr; }

rjoshi
  • 1,645
  • 1
  • 20
  • 31

1 Answers1

12

Use this syntax instead for your nested typedefs:

typedef typename conn_table_t::template nth_index<0>::type conn_table_by_id_type;

The typename keyword is used here as a qualifier to let the compiler know that conn_table_t::template nth_index<0>::type is a type. This special use of typename is only necessary within templates.

The template keyword is used here as a qualifier to distingush member templates from other names.


Furthermore, this line is invalid:

typedef boost::shared_ptr conn_ptr_t;

You can't typedef templates. You can only typedef types. Perhaps you meant to write:

typedef typename boost::shared_ptr<T> conn_ptr_t;

One last error: You're attempting to give two typedefs the same name: conn_table_by_id_type


You should use BOOST_MULTI_INDEX_CONST_MEM_FUN(T, std::string, id) instead of BOOST_MULTI_INDEX_CONST_MEM_FUN(T, std::string, T::id), as documented here.


In response to your last comment: This snippet compiles for me:

void foo(std::string id)
{
    conn_table_by_id_type& id_type_view = conn_table_.template get<0>();
    typename conn_table_by_id_type::const_iterator it = id_type_view.find(id);
}

Where foo is a member function inside the conn_mgr template. I'm guessing that the above is what you were trying to do.

You should write helper methods that get references to your three different conn_table_ indices. This will make things much more concise. For example:

conn_table_by_id_type & by_id_type() {return conn_table_.template get<0>();}

void foo2(std::string id)
{
    typename conn_table_by_id_type::const_iterator it = by_id_type().find(id);
}
Emile Cormier
  • 28,391
  • 15
  • 94
  • 122
  • Emile, thx a lot. Also I learnt a lesson of using typename. Eg. When I tried std::vector::iterator, it gave error but once I converted to typename std::vector::iterator, it worked. – rjoshi Mar 10 '11 at 13:10
  • Hi Emile, now when I use the conm_mgr class as shown above, I get error "No type named "T" in class smpp_conn. I am passing "smpp_conn" class object as first template parameter "T" in conn_mgr class. – rjoshi Mar 10 '11 at 13:57
  • @Emile: that worked. Need one more help. How do I find and iterator? e.g typedef typename conn_table_t::template nth_index<0>::type conn_table_by_id_type; conn_table_by_id_type *id_type_view; typename conn_table_by_id_type::const_iterator it = id_type_view->find(id); gives error on scalar conversion for it. – rjoshi Mar 10 '11 at 15:58
  • @rjoshi: You can't invoke methods on the uniniatized pointer `*id_type_view`. See revised answer. – Emile Cormier Mar 10 '11 at 17:46
  • @Emile: thx. I was getting iterator from index 2 and assigning to id_view which is index 1. But I like you idea of creating a wrapper function. Thx a lot again. – rjoshi Mar 11 '11 at 14:33