How to implement fill constructor and range constructor for sequence containers unambiguously

拜拜、爱过 提交于 2019-12-13 04:39:26

问题


Sequence containers need to have fill constructors and range constructors, i.e. these must both work, assuming MyContainer models a sequence container whose value_type is int and size_type is std::size_t:

// (1) Constructs a MyContainer containing the number '42' 4 times.
MyContainer<int> c = MyContainer<int>(4, 42);

// (2) Constructs a MyContainer containing the elements in the range (array.begin(), array.end())
std::array<int, 4> array = {1, 2, 3, 4};
MyContainer<int> c2 = MyContainer<int>(array.begin(), array.end());

Trouble is, I'm not sure how to implement these two constructors. These signatures don't work:

template<typename T>
MyContainer<T>::MyContainer(const MyContainer::size_type n, const MyContainer::value_type& val);

template<typename T>
template<typename OtherIterator>
MyContainer<T>::MyContainer(OtherIterator i, OtherIterator j);

In this case, an instantiation like in example 1 above selects the range constructor instead of fill constructor, since 4 is an int, not a size_type. It works if I pass in 4u, but if I understand the requirements correctly, any positive integer should work.

If I template the fill constructor on the size type to allow other integers, the call is ambiguous when value_type is the same as the integer type used.

I had a look at the Visual C++ implementation for std::vector and they use some special magic to only enable the range constructor when the template argument is an iterator (_Is_iterator<_Iter>). I can't find any way of implementing this with standard C++.

So my question is... how do I make it work?

Note: I am not using a C++11 compiler, and boost is not an option.


回答1:


I think you've got the solution space right: Either disambiguate the call by passing in only explicitly size_t-typed ns, or use SFINAE to only apply the range constructor to actual iterators. I'll note, however, that there's nothing "magic" (that is, nothing based on implementation-specific extensions) about MSVC's _Is_iterator. The source is available, and it's basically just a static test that the type isn't an integral type. There's a whole lot of boilerplate code backing it up, but it's all standard C++.

A third option, of course, would be to add another fill constructor overload which takes a signed size.



来源:https://stackoverflow.com/questions/21042872/how-to-implement-fill-constructor-and-range-constructor-for-sequence-containers

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!