views:

295

answers:

2

Hello,

I learned in THIS THREAD how a hashed_unique<> index can be used with a composite_key using an int and a std::vector<int>. But unfortunately the following code produces quite an error message:

1> boost/multi_index/hashed_index.hpp(439) : error C2784: 'size_t .. composite_key_hash<...>::operator ()(const boost::tuples::tuple<...> &) const' : could not deduce template argument for 'const boost::tuples::tuple<...> &' from 'const unique_property'

Here the code, does anyone know whats wrong? :-?

    #include <boost/multi_index_container.hpp>
    #include <boost/multi_index/hashed_index.hpp>
    #include <boost/multi_index/random_access_index.hpp>
    #include <boost/multi_index/mem_fun.hpp>
    #include <boost/multi_index/composite_key.hpp>

    #include <vector>

    using boost::multi_index_container;
    using namespace boost::multi_index;


    class unique_property
    {
    private:
      int  my_value;

      //the pair of int and std::vector<int> shall be unique
      int my_int;
      std::vector<int>  my_vec;

    public:
        //stupid ctor (my_values are unique as well, but thats not the point here)
        unique_property(int input_value)
        : my_value(input_value), my_int(10), my_vec(my_int,my_value)
        {}

        int get_int() const {return my_int;}
        const std::vector<int> & get_vec() const {return my_vec;}
    };



    struct hugo{};



    typedef multi_index_container<
      unique_property,
      indexed_by<
        hashed_unique< tag<hugo> ,// indexed by my_int and every entry of my_vec
          composite_key< 
            unique_property,
            const_mem_fun<unique_property,int,&unique_property::get_int >,
            const_mem_fun<unique_property,
                          const std::vector<int> &,&unique_property::get_vec >
          >
        >,
        random_access< >
      >
    > property_locator;

    // for brevity
    typedef property_locator::index<hugo>::type ProbLocByHugo;


    void dummy_test()
    {
        property_locator local_data_structure;
        unique_property tempy(5);

        ProbLocByHugo::iterator pos = local_data_structure.get<hugo>().find(tempy);

        //if (pos == local_data_structure.get<hugo>().end() )
        //    local_data_structure.insert(tempy);
        //else
        //{
        //    local_data_structure.get<hugo>().replace(pos,tempy);
        //}
    }

The complete error messages are:

    1>------ Build started: Project: buggy, Configuration: Debug Win32 ------
    1>Compiling...
    1>c:\myPath\boost_1_37_0\include\boost-1_37\boost\multi_index\hashed_index.hpp(439) : error C2784: 'size_t boost::multi_index::composite_key_hash<Hash0,Hash1,Hash2,Hash3,Hash4,Hash5,Hash6,Hash7,Hash8,Hash9>::operator ()(const boost::tuples::tuple<Value0,Value1,Value2,Value3,Value4,Value5,Value6,Value7,Value8,Value9> &) const' : could not deduce template argument for 'const boost::tuples::tuple<Value0,Value1,Value2,Value3,Value4,Value5,Value6,Value7,Value8,Value9> &' from 'const unique_property'
    1>        with
    1>        [
    1>            Hash0=boost::hash<int>,
    1>            Hash1=boost::hash<const std::vector<int>>,
    1>            Hash2=boost::tuples::null_type,
    1>            Hash3=boost::tuples::null_type,
    1>            Hash4=boost::tuples::null_type,
    1>            Hash5=boost::tuples::null_type,
    1>            Hash6=boost::tuples::null_type,
    1>            Hash7=boost::tuples::null_type,
    1>            Hash8=boost::tuples::null_type,
    1>            Hash9=boost::tuples::null_type
    1>        ]
    1>        c:\myPath\boost_1_37_0\include\boost-1_37\boost\multi_index\composite_key.hpp(1099) : see declaration of 'boost::multi_index::composite_key_hash<Hash0,Hash1,Hash2,Hash3,Hash4,Hash5,Hash6,Hash7,Hash8,Hash9>::operator ()'
    1>        with
    1>        [
    1>            Hash0=boost::hash<int>,
    1>            Hash1=boost::hash<const std::vector<int>>,
    1>            Hash2=boost::tuples::null_type,
    1>            Hash3=boost::tuples::null_type,
    1>            Hash4=boost::tuples::null_type,
    1>            Hash5=boost::tuples::null_type,
    1>            Hash6=boost::tuples::null_type,
    1>            Hash7=boost::tuples::null_type,
    1>            Hash8=boost::tuples::null_type,
    1>            Hash9=boost::tuples::null_type
    1>        ]
    1>        c:\myPath\boost_1_37_0\include\boost-1_37\boost\multi_index\hashed_index.hpp(429) : see reference to function template instantiation 'boost::multi_index::detail::hashed_index_iterator<Node,BucketArray> boost::multi_index::detail::hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>::find<CompatibleKey,boost::hash<T>,std::equal_to<_Ty>>(const CompatibleKey &,const CompatibleHash &,const CompatiblePred &) const' being compiled
    1>        with
    1>        [
    1>            Node=boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::random_access_index_node<boost::multi_index::detail::index_node_base<unique_property,std::allocator<unique_property>>>>,
    1>            BucketArray=boost::multi_index::detail::bucket_array<std::allocator<unique_property>>,
    1>            KeyFromValue=boost::multi_index::composite_key<unique_property,boost::multi_index::const_mem_fun<unique_property,int,unique_property::get_int>,boost::multi_index::const_mem_fun<unique_property,const std::vector<int> &,unique_property::get_vec>>,
    1>            Hash=boost::hash<boost::multi_index::composite_key_result<boost::multi_index::composite_key<unique_property,boost::multi_index::const_mem_fun<unique_property,int,unique_property::get_int>,boost::multi_index::const_mem_fun<unique_property,const std::vector<int> &,unique_property::get_vec>>>>,
    1>            Pred=std::equal_to<boost::multi_index::composite_key_result<boost::multi_index::composite_key<unique_property,boost::multi_index::const_mem_fun<unique_property,int,unique_property::get_int>,boost::multi_index::const_mem_fun<unique_property,const std::vector<int> &,unique_property::get_vec>>>>,
    1>            SuperMeta=boost::multi_index::detail::nth_layer<1,unique_property,boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<hugo>,boost::multi_index::composite_key<unique_property,boost::multi_index::const_mem_fun<unique_property,int,unique_property::get_int>,boost::multi_index::const_mem_fun<unique_property,const std::vector<int> &,unique_property::get_vec>>>,boost::multi_index::random_access<>>,std::allocator<unique_property>>,
    1>            TagList=boost::mpl::vector1<hugo>,
    1>            Category=boost::multi_index::detail::hashed_unique_tag,
    1>            CompatibleKey=unique_property,
    1>            T=boost::multi_index::composite_key_result<boost::multi_index::composite_key<unique_property,boost::multi_index::const_mem_fun<unique_property,int,unique_property::get_int>,boost::multi_index::const_mem_fun<unique_property,const std::vector<int> &,unique_property::get_vec>>>,
    1>            _Ty=boost::multi_index::composite_key_result<boost::multi_index::composite_key<unique_property,boost::multi_index::const_mem_fun<unique_property,int,unique_property::get_int>,boost::multi_index::const_mem_fun<unique_property,const std::vector<int> &,unique_property::get_vec>>>,
    1>            CompatibleHash=boost::hash<boost::multi_index::composite_key_result<boost::multi_index::composite_key<unique_property,boost::multi_index::const_mem_fun<unique_property,int,unique_property::get_int>,boost::multi_index::const_mem_fun<unique_property,const std::vector<int> &,unique_property::get_vec>>>>,
    1>            CompatiblePred=std::equal_to<boost::multi_index::composite_key_result<boost::multi_index::composite_key<unique_property,boost::multi_index::const_mem_fun<unique_property,int,unique_property::get_int>,boost::multi_index::const_mem_fun<unique_property,const std::vector<int> &,unique_property::get_vec>>>>
    1>        ]
    1>        c:\documents and settings\amenge.dedekind\desktop\ggt_test\mem_rw_test.cpp(886) : see reference to function template instantiation 'boost::multi_index::detail::hashed_index_iterator<Node,BucketArray> boost::multi_index::detail::hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>::find<unique_property>(const CompatibleKey &) const' being compiled
    1>        with
    1>        [
    1>            Node=boost::multi_index::detail::hashed_index_node<boost::multi_index::detail::random_access_index_node<boost::multi_index::detail::index_node_base<unique_property,std::allocator<unique_property>>>>,
    1>            BucketArray=boost::multi_index::detail::bucket_array<std::allocator<unique_property>>,
    1>            KeyFromValue=boost::multi_index::composite_key<unique_property,boost::multi_index::const_mem_fun<unique_property,int,unique_property::get_int>,boost::multi_index::const_mem_fun<unique_property,const std::vector<int> &,unique_property::get_vec>>,
    1>            Hash=boost::hash<boost::multi_index::composite_key_result<boost::multi_index::composite_key<unique_property,boost::multi_index::const_mem_fun<unique_property,int,unique_property::get_int>,boost::multi_index::const_mem_fun<unique_property,const std::vector<int> &,unique_property::get_vec>>>>,
    1>            Pred=std::equal_to<boost::multi_index::composite_key_result<boost::multi_index::composite_key<unique_property,boost::multi_index::const_mem_fun<unique_property,int,unique_property::get_int>,boost::multi_index::const_mem_fun<unique_property,const std::vector<int> &,unique_property::get_vec>>>>,
    1>            SuperMeta=boost::multi_index::detail::nth_layer<1,unique_property,boost::multi_index::indexed_by<boost::multi_index::hashed_unique<boost::multi_index::tag<hugo>,boost::multi_index::composite_key<unique_property,boost::multi_index::const_mem_fun<unique_property,int,unique_property::get_int>,boost::multi_index::const_mem_fun<unique_property,const std::vector<int> &,unique_property::get_vec>>>,boost::multi_index::random_access<>>,std::allocator<unique_property>>,
    1>            TagList=boost::mpl::vector1<hugo>,
    1>            Category=boost::multi_index::detail::hashed_unique_tag,
    1>            CompatibleKey=unique_property
    1>        ]
    1>c:\myPath\boost_1_37_0\include\boost-1_37\boost\multi_index\hashed_index.hpp(439) : error C2784: 'size_t boost::multi_index::composite_key_hash<Hash0,Hash1,Hash2,Hash3,Hash4,Hash5,Hash6,Hash7,Hash8,Hash9>::operator ()(const boost::multi_index::composite_key_result<CompositeKey1> &) const' : could not deduce template argument for 'const boost::multi_index::composite_key_result<CompositeKey1> &' from 'const unique_property'
    1>        with
    1>        [
    1>            Hash0=boost::hash<int>,
    1>            Hash1=boost::hash<const std::vector<int>>,
    1>            Hash2=boost::tuples::null_type,
    1>            Hash3=boost::tuples::null_type,
    1>            Hash4=boost::tuples::null_type,
    1>            Hash5=boost::tuples::null_type,
    1>            Hash6=boost::tuples::null_type,
    1>            Hash7=boost::tuples::null_type,
    1>            Hash8=boost::tuples::null_type,
    1>            Hash9=boost::tuples::null_type
    1>        ]
    1>        c:\myPath\boost_1_37_0\include\boost-1_37\boost\multi_index\composite_key.hpp(1083) : see declaration of 'boost::multi_index::composite_key_hash<Hash0,Hash1,Hash2,Hash3,Hash4,Hash5,Hash6,Hash7,Hash8,Hash9>::operator ()'
    1>        with
    1>        [
    1>            Hash0=boost::hash<int>,
    1>            Hash1=boost::hash<const std::vector<int>>,
    1>            Hash2=boost::tuples::null_type,
    1>            Hash3=boost::tuples::null_type,
    1>            Hash4=boost::tuples::null_type,
    1>            Hash5=boost::tuples::null_type,
    1>            Hash6=boost::tuples::null_type,
    1>            Hash7=boost::tuples::null_type,
    1>            Hash8=boost::tuples::null_type,
    1>            Hash9=boost::tuples::null_type
    1>        ]
    1>c:\myPath\boost_1_37_0\include\boost-1_37\boost\multi_index\hashed_index.hpp(443) : error C2784: 'bool boost::multi_index::composite_key_equal_to<Pred0,Pred1,Pred2,Pred3,Pred4,Pred5,Pred6,Pred7,Pred8,Pred9>::operator ()(const boost::tuples::tuple<Value0,Value1,Value2,Value3,Value4,Value5,Value6,Value7,Value8,Value9> &,const boost::multi_index::composite_key_result<CompositeKey> &) const' : could not deduce template argument for 'const boost::tuples::tuple<Value0,Value1,Value2,Value3,Value4,Value5,Value6,Value7,Value8,Value9> &' from 'const unique_property'
    1>        with
    1>        [
    1>            Pred0=std::equal_to<int>,
    1>            Pred1=std::equal_to<const std::vector<int>>,
    1>            Pred2=boost::tuples::null_type,
    1>            Pred3=boost::tuples::null_type,
    1>            Pred4=boost::tuples::null_type,
    1>            Pred5=boost::tuples::null_type,
    1>            Pred6=boost::tuples::null_type,
    1>            Pred7=boost::tuples::null_type,
    1>            Pred8=boost::tuples::null_type,
    1>            Pred9=boost::tuples::null_type
    1>        ]
    1>        c:\myPath\boost_1_37_0\include\boost-1_37\boost\multi_index\composite_key.hpp(914) : see declaration of 'boost::multi_index::composite_key_equal_to<Pred0,Pred1,Pred2,Pred3,Pred4,Pred5,Pred6,Pred7,Pred8,Pred9>::operator ()'
    1>        with
    1>        [
    1>            Pred0=std::equal_to<int>,
    1>            Pred1=std::equal_to<const std::vector<int>>,
    1>            Pred2=boost::tuples::null_type,
    1>            Pred3=boost::tuples::null_type,
    1>            Pred4=boost::tuples::null_type,
    1>            Pred5=boost::tuples::null_type,
    1>            Pred6=boost::tuples::null_type,
    1>            Pred7=boost::tuples::null_type,
    1>            Pred8=boost::tuples::null_type,
    1>            Pred9=boost::tuples::null_type
    1>        ]
    1>c:\myPath\boost_1_37_0\include\boost-1_37\boost\multi_index\hashed_index.hpp(443) : error C2784: 'bool boost::multi_index::composite_key_equal_to<Pred0,Pred1,Pred2,Pred3,Pred4,Pred5,Pred6,Pred7,Pred8,Pred9>::operator ()(const boost::multi_index::composite_key_result<CompositeKey1> &,const boost::tuples::tuple<Value0,Value1,Value2,Value3,Value4,Value5,Value6,Value7,Value8,Value9> &) const' : could not deduce template argument for 'const boost::multi_index::composite_key_result<CompositeKey1> &' from 'const unique_property'
    1>        with
    1>        [
    1>            Pred0=std::equal_to<int>,
    1>            Pred1=std::equal_to<const std::vector<int>>,
    1>            Pred2=boost::tuples::null_type,
    1>            Pred3=boost::tuples::null_type,
    1>            Pred4=boost::tuples::null_type,
    1>            Pred5=boost::tuples::null_type,
    1>            Pred6=boost::tuples::null_type,
    1>            Pred7=boost::tuples::null_type,
    1>            Pred8=boost::tuples::null_type,
    1>            Pred9=boost::tuples::null_type
    1>        ]
    1>        c:\myPath\boost_1_37_0\include\boost-1_37\boost\multi_index\composite_key.hpp(889) : see declaration of 'boost::multi_index::composite_key_equal_to<Pred0,Pred1,Pred2,Pred3,Pred4,Pred5,Pred6,Pred7,Pred8,Pred9>::operator ()'
    1>        with
    1>        [
    1>            Pred0=std::equal_to<int>,
    1>            Pred1=std::equal_to<const std::vector<int>>,
    1>            Pred2=boost::tuples::null_type,
    1>            Pred3=boost::tuples::null_type,
    1>            Pred4=boost::tuples::null_type,
    1>            Pred5=boost::tuples::null_type,
    1>            Pred6=boost::tuples::null_type,
    1>            Pred7=boost::tuples::null_type,
    1>            Pred8=boost::tuples::null_type,
    1>            Pred9=boost::tuples::null_type
    1>        ]
    1>c:\myPath\boost_1_37_0\include\boost-1_37\boost\multi_index\hashed_index.hpp(443) : error C2784: 'bool boost::multi_index::composite_key_equal_to<Pred0,Pred1,Pred2,Pred3,Pred4,Pred5,Pred6,Pred7,Pred8,Pred9>::operator ()(const boost::multi_index::composite_key_result<CompositeKey1> &,const boost::multi_index::composite_key_result<CompositeKey2> &) const' : could not deduce template argument for 'const boost::multi_index::composite_key_result<CompositeKey1> &' from 'const unique_property'
    1>        with
    1>        [
    1>            Pred0=std::equal_to<int>,
    1>            Pred1=std::equal_to<const std::vector<int>>,
    1>            Pred2=boost::tuples::null_type,
    1>            Pred3=boost::tuples::null_type,
    1>            Pred4=boost::tuples::null_type,
    1>            Pred5=boost::tuples::null_type,
    1>            Pred6=boost::tuples::null_type,
    1>            Pred7=boost::tuples::null_type,
    1>            Pred8=boost::tuples::null_type,
    1>            Pred9=boost::tuples::null_type
    1>        ]
    1>        c:\myPath\boost_1_37_0\include\boost-1_37\boost\multi_index\composite_key.hpp(859) : see declaration of 'boost::multi_index::composite_key_equal_to<Pred0,Pred1,Pred2,Pred3,Pred4,Pred5,Pred6,Pred7,Pred8,Pred9>::operator ()'
    1>        with
    1>        [
    1>            Pred0=std::equal_to<int>,
    1>            Pred1=std::equal_to<const std::vector<int>>,
    1>            Pred2=boost::tuples::null_type,
    1>            Pred3=boost::tuples::null_type,
    1>            Pred4=boost::tuples::null_type,
    1>            Pred5=boost::tuples::null_type,
    1>            Pred6=boost::tuples::null_type,
    1>            Pred7=boost::tuples::null_type,
    1>            Pred8=boost::tuples::null_type,
    1>            Pred9=boost::tuples::null_type
    1>        ]
A: 

Okay Let's get working (comments just allow so much).

The problem stems from the invocation of the find method.

The template elected is:

template<
  typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
>
iterator find(const CompatibleKey& k,
              const CompatibleHash& hash,
              const CompatiblePred& eq) const;

With:

KeyFromValue = composite_key<...>
CompatibleKey = unique_property
CompatibleHash = boost::hash<KeyFromValue>
CompatiblePred = equal_to<KeyFromValue>

Apparently, the invocation hash(k) inside the find method fails for the reason cited (could not deduce...), this methods itself invokes:

template<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(typename Value)>
std::size_t operator()(const tuple<BOOST_MULTI_INDEX_CK_ENUM_PARAMS(Value)>& x)const

(Don't be afraid by the macro, it's just some magic Boost.Preprocessor to enumerate the Value from 0 to 9)

Now, from this we can see that the problem is that we try to build tuple<Value0, Value1, ..., Value9> from CompatibleKey ie unique_property and it does not work.

I think you should try:

ProbLocByHugo::iterator pos =
  local_data_structure.get<hugo>().find(boost::make_tuple(tempy));

Here is the example of composite_key from [Boost][1]:

file_system_by_name::iterator it=fs.find(
  boost::make_tuple(current_dir,dir));

boost::tie(it0,it1)=fs_by_size.equal_range(
    boost::make_tuple(current_dir));

As you can see, any invocation of key usage leads to make_tuple.

You could avoid this by providing the right conversion operator for your unique_property class.

operator boost::tuple< int, std::vector<int> const& >() const
  { return boost::make_tuple(my_int, cref(my_vec)); }

Or perhaps a variation...

I have to admit that I am a bit disappointed by this requirement, I would have expected that find would work seemlessly.

[1] http://www.boost.org/doc/libs/1%5F40%5F0/libs/multi%5Findex/example/composite%5Fkeys.cpp

Matthieu M.
Hi, thank you very much for your time and your solution! I tried your first approach but it didn't work right away. After thinking about your second suggestion I tried the following call: `ProbLocByHugo::iterator pos = local_data_structure.get<hugo>().find(boost::make_tuple(tempy.get_int(),tempy.get_vec()));` And that did the trick! Thank you again for your much appreciated help!! Have a great day!
Dane
You're welcome, I still don't get why this is not automatic anyway, as you have given the extraction method in template parameter...
Matthieu M.
A: 

Hi, Matthieu hints at the problem but probably does not expclicitly pinpoint it: find() expects a key or a compatible key and you're passing a whole element. How do you extract the key from tempy? There are two ways:

  • Construct a compatible tuple as Matthieu shows.
  • Each index provides a key_extractor() member function that returns a copy of the internal key extractor (here, a value of composite_key<...>) for you to use:

ProbLocByHugo::iterator pos = local_data_structure.get<hugo>().find( local_data_structure.get<hugo>().key_extractor()(tempy));

Hope this helps.

Joaquín M López Muñoz
Hi, thank you for your additional information. But I don't see, how boost is not able to get these information by itself. I mean: I'm saying in the definition of the `composite_key` how to get the necessary members of an element/object of type `unique_property`, why do I have to do it again in any find-statement? On the other hand it is quite useful to be able to put just the necessary parts in a find-statement (if a complete element/object is expensive to build). But I think both ways wouldn't be that hard to implement... But thanks again for your info!
Dane
I *could* add an overload of `find()` that takes whole elements rather than keys but I prefer to keep it terse becausethis is how STL containers work, they expect keys, not whole elements (cf. `std::map`), and because in some pathological cases, such overload would result in a problem: consider the following element type:`struct element{ const element}; ...private: element* k;};`and a `multi_index_container` with `const_mem_fun<element,const elementc.find(x);`Left as an exercise for the reader :-)
Joaquín M López Muñoz