The vector class has these two constructors (among others):
explicit vector(size_type n);
template <class InputIterator>
vector(InputIterator first, InputIterator last, const Allocator& = Allocator());
Naturally I can construct a vector like this, and the int->size_t promotion calls the first constructor:
std::vector v(5);
No problems yet. The problem is if you replace the iterator version with a range version, you get something like this (my class is called Array):
explicit Array(size_t n, const Allocator& = Allocator());
template <typename InputRange>
explicit Array(InputRange r, const Allocator& = Allocator());
The difference is they now have the same number of arguments. So when you call this:
Array<int> a(5);
You have two possibilities:
1) Perform int->size_t promotion and call the first constructor
2) Call range version using InputRange=int
And the second one is chosen, thus failing to compile because the expected range methods (Front, PopFront, Empty) can't be called on an int. This is a trivial problem to work around (cast to size_t, add int overload, etc.), I feel there has to be a better way. I've been trying to find a way to reduce the overload set to not include the range version on integral types, but I can't seem to get it working in all cases. Here was my first attempt:
template <typename InputRange>
explicit Array(typename std::enable_if<!std::is_integral<InputRange>::value, InputRange>::type r, const Allocator& = Allocator());
This correctly forces an int to call the size_t constructor, but also is trying to make a range take the size_t constructor too. I haven't really figured out why, since I've tried printing out the result of that expression and the type is correct. However, since that's pretty un-readable, I'd rather put the enable_if elsewhere, like in an extra parameter like this:
template <typename InputRange>
explicit Array(InputRange r, const Allocator& = Allocator(), typename std::enable_if<!std::is_integral<InputRange>::value, void>::type* = nullptr);
And for some reason this overload works. So can someone explain why putting the enable_if on the first parameter wasn't working? I'd also be interested in hearing if there's other ideas on how to work around this problem out there.
Thanks.