0

I've run into an issue where, for a dependent type, boost::multi_index::multi_index_container<...>::get<C>() breaks if C is a dependent type. The same does not occur if it's not dependent. MCVE, g++ 7.1.0 (also 6.3.0 if you declare is_same_v<>):

#include <type_traits>                                                                                             
#include <boost/multi_index_container.hpp>                                                                         
#include <boost/multi_index/ordered_index.hpp>                                                                     
#include <boost/multi_index/identity.hpp>                                                                          
#include <boost/multi_index/member.hpp>                                                                            
#include <boost/multi_index/mem_fun.hpp>                                                                           
#include <boost/multi_index/random_access_index.hpp>                                                               

#define MEMBER(T, M)        boost::multi_index::member<T, decltype(T::M), &T::M>                                   
#define TAGNMEMBER(T, M)    boost::multi_index::tag<MEMBER(T, M)>, MEMBER(T, M)                                    

namespace ns1 {                                                                                                    
    struct Elem {                                                                                                  
        size_t id_;                                                                                                

        bool operator<(const Elem& rhs) const { return id_ < rhs.id_; }                                            
    };                                                                                                             

    using Cont = boost::multi_index::multi_index_container<                                                        
        Elem,                                                                                                      
        boost::multi_index::indexed_by<                                                                            
            boost::multi_index::ordered_unique<boost::multi_index::identity<Elem>>,                                
            boost::multi_index::ordered_unique<TAGNMEMBER(Elem, id_)>                                              
        >                                                                                                          
    >;                                                                                                             
}                                                                                                                  

namespace ns2 {                                                                                                    
//    void f(ns1::Cont& cont) // always works                                                                      
    template<typename C>                                                                                           
    void f(C& cont)                                                                                                
    {                                                                                                              
        ns1::Cont& c = cont;                                                                                       
        static_assert(std::is_same_v<decltype(cont), ns1::Cont&>);                                                 
        cont.get<MEMBER(ns1::Elem, id_)>(); // v1 - error if dependent type                                        
        //c.get<MEMBER(ns1::Elem, id_)>();  // v2 - always works                                                   
    }                                                                                                              
}                                                                                                                  


int main()                                                                                                         
{                                                                                                                  
    ns1::Cont cont;                                                                                                
    cont.insert({0});                                                                                              
    ns2::f(cont);                                                                                                  
}

Could you please advise?

lorro
  • 10,687
  • 23
  • 36

1 Answers1

2

Indicate that get is a template:

cont.template get<MEMBER(ns1::Elem, id_)>(); // now works

It works with c, since you explicitly declare the type of it (ns1::Cont), therefore, get is not dependent any more.

erenon
  • 18,838
  • 2
  • 61
  • 93