Search code examples
boostboost-multi-indextemplate-instantiation

Why is this member function a duplicate?


I have some code that's worked on VS10 and works on several other platforms, but causes a strange error on VS2015. The error (in a template expansion inside Boost) is very strange because it points to a form without const and tells me that it duplicates the previous member function immediately before it in the source, which is a variation that adds const.

Here is a minimal example I've managed to distill from the offending program.

#define BOOST_MULTI_INDEX_DISABLE_SERIALIZATION
#include "boost/multi_index_container.hpp"
#include "boost/multi_index/key_extractors.hpp"
#include "boost/multi_index/ordered_index.hpp"

class C1 { };

class  C2 {
public:
    uint32_t xx1;
    C1 f2() const;
};

namespace bmi = boost::multi_index;

typedef boost::multi_index_container<
    std::shared_ptr< const C2 >,
    bmi::indexed_by<
        bmi::ordered_unique<
            bmi::tag<C1>,
            bmi::composite_key<
                const C2,
                bmi::const_mem_fun< C2, C1, &C2::f2 >,
                bmi::member< C2, const uint32_t, &C2::xx1 >
            > // composite
        > // ordered_unique
    > // indexed_by
> BadContainerBase;

struct BadType : public BadContainerBase { };

I'm using VS2015 with x86 (32-bit) targeted.

The full error is:

E:\C++Libs\boost_1_59_0\boost/multi_index/composite_key.hpp(638): error C2535: 'boost::multi_index::composite_key_result<boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>> boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>::operator ()(const boost::reference_wrapper<const Class> &) const': member function already defined or declared
        with
        [
            Class=C2
        ]
E:\C++Libs\boost_1_59_0\boost/multi_index/composite_key.hpp(632): note: see declaration of 'boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>::operator ()'
E:\C++Libs\boost_1_59_0\boost/multi_index/detail/ord_index_args.hpp(46): note: see reference to class template instantiation 'boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>' being compiled
E:\C++Libs\boost_1_59_0\boost/mpl/eval_if.hpp(41): note: see reference to class template instantiation 'boost::multi_index::detail::index_args_default_compare<boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>>' being compiled
E:\C++Libs\boost_1_59_0\boost/multi_index/detail/ord_index_args.hpp(70): note: see reference to class template instantiation 'boost::mpl::eval_if<boost::mpl::is_na<boost::mpl::na>,boost::multi_index::detail::index_args_default_compare<boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>>,boost::mpl::identity<boost::mpl::na>>' being compiled
E:\C++Libs\boost_1_59_0\boost/multi_index/ordered_index.hpp(65): note: see reference to class template instantiation 'boost::multi_index::detail::ordered_index_args<Arg1,Arg2,Arg3>' being compiled
        with
        [
            Arg1=boost::multi_index::tag<C1,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,
            Arg2=boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,
            Arg3=boost::mpl::na
        ]
E:\C++Libs\boost_1_59_0\boost/multi_index/detail/node_type.hpp(44): note: see reference to class template instantiation 'boost::multi_index::ordered_unique<boost::multi_index::tag<C1,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::mpl::na>' being compiled
E:\C++Libs\boost_1_59_0\boost/mpl/aux_/preprocessed/plain/apply_wrap.hpp(49): note: see reference to class template instantiation 'boost::multi_index::detail::index_node_applier::apply<T1,T2>' being compiled
        with
        [
            T1=boost::mpl::v_iter<boost::mpl::vector1<boost::multi_index::ordered_unique<boost::multi_index::tag<C1,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::mpl::na>>,0>,
            T2=boost::multi_index::detail::index_node_base<std::shared_ptr<const C2>,std::allocator<std::shared_ptr<const C2>>>
        ]
E:\C++Libs\boost_1_59_0\boost/mpl/aux_/preprocessed/plain/bind.hpp(207): note: see reference to class template instantiation 'boost::mpl::apply_wrap2<boost::multi_index::detail::index_node_applier,boost::mpl::v_iter<boost::mpl::vector1<T0>,0>,boost::multi_index::detail::index_node_base<Value,Allocator>>' being compiled
        with
        [
            T0=boost::multi_index::ordered_unique<boost::multi_index::tag<C1,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::mpl::na>,
            Value=std::shared_ptr<const C2>,
            Allocator=std::allocator<std::shared_ptr<const C2>>
        ]
E:\C++Libs\boost_1_59_0\boost/mpl/aux_/preprocessed/plain/apply_wrap.hpp(49): note: see reference to class template instantiation 'boost::mpl::bind2<boost::multi_index::detail::index_node_applier,boost::mpl::_2,boost::mpl::_  ::apply<T1,T2,boost::mpl::na,boost::mpl::na,boost::mpl::na>' being compiled
        with
        [
            T1=boost::multi_index::detail::index_node_base<std::shared_ptr<const C2>,std::allocator<std::shared_ptr<const C2>>>,
            T2=boost::mpl::v_iter<boost::mpl::vector1<boost::multi_index::ordered_unique<boost::multi_index::tag<C1,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::mpl::na>>,0>
        ]
E:\C++Libs\boost_1_59_0\boost/mpl/aux_/preprocessed/plain/apply.hpp(63): note: see reference to class template instantiation 'boost::mpl::apply_wrap2<boost::mpl::bind2<boost::multi_index::detail::index_node_applier,boost::mpl::_2,boost::mpl::_  ,T1,T2>' being compiled
        with
        [
            T1=boost::multi_index::detail::index_node_base<std::shared_ptr<const C2>,std::allocator<std::shared_ptr<const C2>>>,
            T2=boost::mpl::v_iter<boost::mpl::vector1<boost::multi_index::ordered_unique<boost::multi_index::tag<C1,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::mpl::na>>,0>
        ]
E:\C++Libs\boost_1_59_0\boost/mpl/aux_/preprocessed/plain/reverse_iter_fold_impl.hpp(58): note: see reference to class template instantiation 'boost::mpl::apply2<BackwardOp,boost::multi_index::detail::index_node_base<Value,Allocator>,boost::mpl::v_iter<boost::mpl::vector1<T0>,0>>' being compiled
        with
        [
            BackwardOp=boost::mpl::bind2<boost::multi_index::detail::index_node_applier,boost::mpl::_2,boost::mpl::_  ,
            Value=std::shared_ptr<const C2>,
            Allocator=std::allocator<std::shared_ptr<const C2>>,
            T0=boost::multi_index::ordered_unique<boost::multi_index::tag<C1,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::mpl::na>
        ]
E:\C++Libs\boost_1_59_0\boost/mpl/reverse_iter_fold.hpp(43): note: see reference to class template instantiation 'boost::mpl::aux::reverse_iter_fold_impl<1,boost::mpl::v_iter<boost::mpl::vector1<T0>,0>,boost::mpl::v_iter<boost::mpl::vector1<T0>,  ,State,boost::mpl::bind2<boost::multi_index::detail::index_node_applier,boost::mpl::_2,boost::mpl::_  ,boost::mpl::protect<boost::mpl::arg<  ,0>>' being compiled
        with
        [
            T0=boost::multi_index::ordered_unique<boost::multi_index::tag<C1,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::mpl::na>,
            State=boost::multi_index::detail::index_node_base<std::shared_ptr<const C2>,std::allocator<std::shared_ptr<const C2>>>
        ]
E:\C++Libs\boost_1_59_0\boost/multi_index/detail/node_type.hpp(57): note: see reference to class template instantiation 'boost::mpl::reverse_iter_fold<IndexSpecifierList,boost::multi_index::detail::index_node_base<Value,Allocator>,boost::mpl::bind2<boost::multi_index::detail::index_node_applier,boost::mpl::_2,boost::mpl::_  ,boost::mpl::arg<  >' being compiled
        with
        [
            IndexSpecifierList=boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::tag<C1,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::mpl::na>,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,
            Value=std::shared_ptr<const C2>,
            Allocator=std::allocator<std::shared_ptr<const C2>>
        ]
E:\C++Libs\boost_1_59_0\boost/multi_index_container.hpp(89): note: see reference to class template instantiation 'boost::multi_index::detail::multi_index_node_type<Value,IndexSpecifierList,Allocator>' being compiled
        with
        [
            Value=std::shared_ptr<const C2>,
            IndexSpecifierList=boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::tag<C1,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::mpl::na>,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,
            Allocator=std::allocator<std::shared_ptr<const C2>>
        ]
Annotation\Model.cpp(40): note: see reference to class template instantiation 'boost::multi_index::multi_index_container<std::shared_ptr<const C2>,boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::tag<C1,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,boost::multi_index::composite_key<const C2,boost::multi_index::const_mem_fun<C2,C1,C1 C2::f2(void) const>,boost::multi_index::member<C2,const uint32_t,pointer-to-member(0x0)>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>,boost::mpl::na>,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na,boost::mpl::na>,std::allocator<Value>>' being compiled
        with
        [
            Value=std::shared_ptr<const C2>
        ]

Looking at the line it reports

// *** this earlier one has ⋯const C2>&⋯ where the error claims the problem lies.
result_type operator()(const reference_wrapper<const value_type>& x)const
{
  return result_type(*this,x.get());
}

result_type operator()(const reference_wrapper<value_type>& x)const
{   // *** error points to this line, and value_type is C2, and the template parameter is =not= const C2.
  return result_type(*this,x.get());
}

What's going on here? This seems to be an ordinary use of boost::multi_index_container.


Solution

  • Your composite_key is wrongly specified, it should be

    bmi::composite_key<
        C2,
        bmi::const_mem_fun< C2, C1, &C2::f2 >,
        bmi::member< C2, const uint32_t, &C2::xx1 >
    >
    

    i.e. without the const qualifier in the first argument. Also, you might want to take a look at this section in Boost.MultiIndex docs, particularly the penultimate paragraph.