0

I’m writing a wrapper that, for the purpose of this question, does nothing but wraps a SequenceContainer ( http://en.cppreference.com/w/cpp/concept/SequenceContainer ) and reproduces all functionality of the SequenceContainer concept the wrapped container offers.

My attempt to write such a wrapper looks like this:

template<class Container>
class SequenceContainerWrapper
{
  Container cont;
public:
  using value_type = typename Container::value_type;
  using reference = typename Container::reference;
  using size_type = typename Container::size_type;
  SequenceContainerWrapper(initializer_list<value_type> init) : cont(init) {}
  reference operator[] (size_type n) {return cont[n];}
  // lots of other code that does nothing but wrapping
};

And yes – I can use it, for example, with std::vector. The below code compiles and works as expected ( http://ideone.com/sYeIeJ ):

int main()
{
    SequenceContainerWrapper<vector<int>> vec({1,2,3,4});
    cout << vec[2] << '\n';
}

However, this constructor won’t work with std::array. This snippet does not compile ( http://ideone.com/5nZhar ):

int main()
{
    SequenceContainerWrapper<array<int, 4>> arr({1,2,3,4});
    cout << arr[2] << '\n';
}

This is because ( http://en.cppreference.com/w/cpp/concept/SequenceContainer#cite_note-1 ):

std::array supports assignment from a braced-init-list, but not from an std::initializer_list

So how can I reproduce in my wrapper the possibility to initialize an std::array with a braced-init-list without sacrificing the genericness of my wrapper and introducing solutions that will cripple the wrapper’s compatibility with e.g. std::vector?

1 Answers1

2

Instead of using:

SequenceContainerWrapper(initializer_list<value_type> init) : cont(init) {}

you could use:

SequenceContainerWrapper(Container init) : cont(std::move(init)) {}

See it working at http://ideone.com/MzRQGC.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Thank you. But, outta simple curiosity: If a copy constructor is everything you need and will also cover initializer list initialization, then why does `std::vector` provide both constructors? http://en.cppreference.com/w/cpp/container/vector/vector We have both `vector( const vector& other );` and `vector( std::initializer_list init );` there. Wouldn’t `vector( const vector& other );` suffice? –  Nov 14 '16 at 23:00
  • My thinking is, that with your excellent solution, there will be one constructor overload of `std::vector` I will not explicitly wrap; so, assuming that the standard library doesn’t provide redundant functions, there will have to be at least one use case of `std::vector` I will fail to cover… –  Nov 14 '16 at 23:02
  • 1
    @gaazkam, if `std::vector` did not provide `vector( std::initializer_list init )`, you won't be able to use a `std::initializer_list` to construct a temporary `std::vector` in the call to construct a `SequenceContainerWrapper`. – R Sahu Nov 14 '16 at 23:04
  • So… there still be one use case of `std::vector` I won’t cover: `SequenceContainerWrapper>> vec2({1,2,3,4});` http://ideone.com/Kv5YtM This is unfortunately an important use-case, since I do nest these wrappers, each alternating the container’s behavior slightly, to achieve the desired outcome with the correct chain of slightly different wrappers. –  Nov 14 '16 at 23:22
  • With the `SequenceContainerWrapper(initializer_list init) : cont(init) {}` I can nest these wrappers http://ideone.com/EKywvb , however unfortunately this ofc breaks `std::array`... Dang. –  Nov 14 '16 at 23:24
  • @gaazkam, Valid points. I am not sure what would work for all of your use cases. – R Sahu Nov 14 '16 at 23:56
  • Why `const&`? That seems premature pessimization. – Yakk - Adam Nevraumont Nov 15 '16 at 00:41
  • @Yakk, if you are hinting at a better solution, I am not sure what it is. Please elaborate a bit. – R Sahu Nov 15 '16 at 02:00
  • @rsahu drop the `const&` and `std::move`? – Yakk - Adam Nevraumont Nov 15 '16 at 02:36
  • @Yakk, if I change `Container const& init` to `Container&& init`, I am not able to use `std::vector v({1,2,3,4}); SequenceContainerWrapper> vec(v);`. I am forced to use `std::vector v({1,2,3,4}); SequenceContainerWrapper> vec(std::move(v));`. I am not sure whether that is better. – R Sahu Nov 15 '16 at 03:00
  • @rsahu I did not say `&&`. Just take by value. – Yakk - Adam Nevraumont Nov 15 '16 at 03:14
  • @Yakk, Thanks for being patient. I am still learning the ways of move semantics. – R Sahu Nov 15 '16 at 03:27