views:

161

answers:

2

Hi,

I've got a strange problem with templates and namespaces...

I have the following code which compiles fine..

using namespace boost::multi_index;

template < typename OT, typename KT, KT (OT::* KM)() const, typename KC, typename CMP >
class OrderBook
{
public:
    OrderBook() {}
    ~OrderBook() {}

    typedef multi_index_container<
        OT,
        indexed_by<
            ordered_unique<
                const_mem_fun< OT, KT, KM >,
                KC
            >,
            ordered_unique<
                identity< OT >,
                CMP
            >
        >
    > Container;

    typedef typename Container::template nth_index< 0 >::type index_0;
    typedef typename Container::template nth_index< 1 >::type index_1;

    typedef typename index_0::const_iterator const_iterator_0;
    typedef typename index_1::const_iterator const_iterator_1;

    const_iterator_0 begin0() const { return _container.get<0>().begin(); }
    const_iterator_0 end0() const { return _container.get<0>().end(); }


public:
    Container _container;
};

However, due to a namespace collision when I insert this code into another project I have to have... (Notice how I've had to remove the using namespace boost::multi_index and manually specify it where needed

template < typename OT, typename KT, KT (OT::* KM)() const, typename KC, typename CMP >
class OrderBook
{
public:
    OrderBook() {}
    ~OrderBook() {}

    typedef boost::multi_index::multi_index_container<
        OT,
        boost::multi_index::indexed_by<
            boost::multi_index::ordered_unique<
                boost::multi_index::const_mem_fun< OT, KT, KM >,
                KC
            >,
            boost::multi_index::ordered_unique<
                boost::multi_index::identity< OT >,
                CMP
            >
        >
    > Container;

    typedef typename Container::template nth_index< 0 >::type index_0;
    typedef typename Container::template nth_index< 1 >::type index_1;

    typedef typename index_0::const_iterator const_iterator_0;
    typedef typename index_1::const_iterator const_iterator_1;

    const_iterator_0 begin0() const { return _container.get<0>().begin(); }
    const_iterator_0 end0() const { return _container.get<0>().end(); }


public:
    Container _container;
};

Which gives me the following error from g++.

In member function 'typename boost::multi_index::multi_index_container<OT, boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::const_mem_fun<OT, KT, KM>, KC, mpl_::na>, boost::multi_index::ordered_unique<boost::multi_index::identity<Value>, CMP, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator<_CharT> >::nth_index<0>::type::const_iterator OrderBook<OT, KT, KM, KC, CMP>::begin0() const':

error: expected primary-expression before ')' token


In member function 'typename boost::multi_index::multi_index_container<OT, boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::const_mem_fun<OT, KT, KM>, KC, mpl_::na>, boost::multi_index::ordered_unique<boost::multi_index::identity<Value>, CMP, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator<_CharT> >::nth_index<0>::type::const_iterator OrderBook<OT, KT, KM, KC, CMP>::end0() const':

error: expected primary-expression before ')' token

Sorry for the long error messages, I did consider cleaning them up but I thought I'd better leave them intact in case I removed something crucial.

I tried this...

typedef typename Container::template boost::multi_index::nth_index< 0 >::type index_0;
typedef typename Container::template boost::multi_index::nth_index< 1 >::type index_1;

and it just made g++ even madder :(

Any ideas?

A: 

Maybe I can guess that some of these functions are not in the boost::multi_index namespace: indexed_b, ordered_unique, const_mem_fun, or identity

Didier Trosset
No, they are all in the boost::multi_index namespace.. I needed to specify them exactly because I had a duplicate with "identity".
ScaryAardvark
+3  A: 

Prefix get<0>() with template:

const_iterator_0 begin0() const { return _container.template get<0>().begin(); }
const_iterator_0 end0  () const { return _container.template get<0>().end();   }

Similar to typename for dependent types, dependent templates have to be prefixed by template:

struct X {
    template<class T> void f();
};

template<class T>
void test() {
    T::f<int>(); // ill-formed
    T::template f<int>(); // ok
}

// ...
test<X>();

And for the curious, that is §14.2/4:

When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6.2), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.

Georg Fritzsche
Thanks. That fixed it.. Can I ask how you found this out or what reference you used. Barring sticking the word "template" everywhere I would have _NEVER_ found this out....
ScaryAardvark
ScaryAardvark, i let gcc point me to the actual line where the problem was and noticed that you refer to a template member function of `_container` and that `_container` was of a template argument type. Dependent templates have to be prefixed by `template`, similar to `typename` for dependent types.
Georg Fritzsche
Correction, i mean `_container` is a template argument dependent type actually - if that is the correct term.
Georg Fritzsche