简体   繁体   中英

How to use boost::assign with custom containers that extend STL containers?

What do I have to do to make custom classes (that inherit from STL containers like std::vector or std::map ) work with the boost::assign list_of() or map_list_of() initializer functions?

Background

I want to easily initialize a containers with a list of values. C++11 introduced initializer lists however I am stuck with C++03 so I cannot use C++11 initializer lists .

As a workaround I found the boost:assign library that provides functions like list_of() and map_list_of(). This works quite well for the STL containers like std::vector and std::map. However if I create my own containers by eg by extending std::vector I get compilation errors.

Example

Here is a small example

#include "boost/assign/list_of.hpp"
using namespace boost::assign;
#include <vector>

struct SpecialVector : public std::vector<int>{
    foo(){/* adds functionality */}
};

int main(){
    std::vector<int> v = list_of(1)(2)(3); // list_of() works well for STL containers

    // The following works but requires adding items one-by-one with push_back
    SpecialVector u; 
    u.push_back(1);
    u.push_back(2);
    u.push_back(3);

    // The following fails when attempting to compile
    SpecialVector u2 = list_of(1)(2)(3);
}

Attempting to compile the example gives me the following error:

In file included from assign_inherited.cpp:1:0:
../../../lib/boost/assign/list_of.hpp: In instantiation of 'Container boost::assign_detail::converter<DerivedTAssign, Iterator>::convert(const Container*, boost::assign_detail::default_type_tag) const [with Container = SpecialVector; DerivedTAssign = boost::assign_detail::generic_list<int>; Iterator = std::_Deque_iterator<int, int&, int*>]':
../../../lib/boost/assign/list_of.hpp:142:38:   required from 'Container boost::assign_detail::converter<DerivedTAssign, Iterator>::convert_to_container() const [with Container = SpecialVector; DerivedTAssign = boost::assign_detail::generic_list<int>; Iterator = std::_Deque_iterator<int, int&, int*>]'
../../../lib/boost/assign/list_of.hpp:436:81:   required from 'boost::assign_detail::generic_list<T>::operator Container() const [with Container = SpecialVector; T = int]'
assign_inherited.cpp:19:39:   required from here
../../../lib/boost/assign/list_of.hpp:163:20: error: no matching function for call to 'SpecialVector::SpecialVector(boost::assign_detail::converter<boost::assign_detail::generic_list<int>, std::_Deque_iterator<int, int&, int*> >::iterator, boost::assign_detail::converter<boost::assign_detail::generic_list<int>, std::_Deque_iterator<int, int&, int*> >::iterator)'
             return Container( begin(), end() );
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~
assign_inherited.cpp:5:8: note: candidate: SpecialVector::SpecialVector()
 struct SpecialVector : public std::vector<int>{
        ^~~~~~~~~~~~~
assign_inherited.cpp:5:8: note:   candidate expects 0 arguments, 2 provided
assign_inherited.cpp:5:8: note: candidate: SpecialVector::SpecialVector(const SpecialVector&)
assign_inherited.cpp:5:8: note:   candidate expects 1 argument, 2 provided

I already checked the documentation of the boost::assign library. I found the section Extending the library , however if I understand it correctly, this section deals with adding custom classes as items in the list , not with generating an initializer for a custom class . Or did I understand this wrong?

Like you said, you need to allow the construction from base types:

Live On Coliru

#include "boost/assign/list_of.hpp"
using namespace boost::assign;
#include <vector>

struct SpecialVector : std::vector<int>{
    typedef std::vector<int> base;
    void foo(){/* adds functionality */}

    SpecialVector() : base() {}
    template <typename T> explicit SpecialVector(T const& t) : base(t) {}
    template <typename T, typename U> SpecialVector(T const& t, U const& u) : base(t, u) {}
    template <typename T, typename U, typename V> SpecialVector(T const& t, U const& u, V const& v) : base(t, u, v) {}
};

int main(){
    std::vector<int> v = list_of(1)(2)(3); // list_of() works well for STL containers

    // The following works but requires adding items one-by-one with push_back
    SpecialVector u; 
    u.push_back(1);
    u.push_back(2);
    u.push_back(3);

    // The following fails when attempting to compile
    SpecialVector u2 = list_of(1)(2)(3);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM