Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

STL Container constructed from other container (e.g. list from vector)

In my code, sometimes I need to construct a container from another container. But these container objects are of different types, so I can't use a copy constructor. What I do looks like this (C++11, I use uniform initialization and constructor delegation) :

std::vector<int> source {1, 3, 5, 7, 9};
std::list<int> destination (source.begin (), source.end ());

I realized that std::list could have a constructor like this, to make things prettier:

template </* ... */>
class list
{
public:
    template <class Container> list (const Container& container)
    : list (container.begin (), container.end ())
    {
    }

    /* ... */
};

Unfortunately I can do this only for my own classes, not for STL classes. So first question, of there a reason such costructors don't exist in STL and Boost? And second question, is there a safe way to implement such a ctor for STL containers, maybe by defining conversion operators somehow?

This issue os of course just a matter of convenience, nothing critical to code or to program behavior. But it could make the code look a bit more readable:

std::vector<int> source {1, 3, 5, 7, 9};
std::list<int> destination = source;
like image 694
cfa45ca55111016ee9269f0a52e771 Avatar asked Mar 23 '23 10:03

cfa45ca55111016ee9269f0a52e771


1 Answers

You should be suspicious of code where the complete range of one container type is copied to another. This is an uncommon activity.

In C++, explicit conversions are usually preferred. Implicit conversions and assignment operators that convert from one type to another are usually discouraged because they sometimes lead to unexpected conversions.

If you truly need to frequently convert between container types, try defining an explicit helper function for the conversion:

template<typename ToType, typename FromType>
ToType container_cast(const FromType& source)
{
    return ToType(source.begin(), source.end(), source.get_allocator());
}

Then your example becomes:

std::vector<int> source {1, 3, 5, 7, 9};
auto destination = container_cast<std::list<int> >(source);
like image 52
joshuanapoli Avatar answered Apr 18 '23 14:04

joshuanapoli