Remove a use of SFINAE in the Range constructor.
authorPhil Willoughby <philwill@fb.com>
Thu, 17 Aug 2017 08:27:07 +0000 (01:27 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Thu, 17 Aug 2017 08:40:15 +0000 (01:40 -0700)
commit6078246acdb8784febc023d5d9e0fb4ddcd81f34
tree986c50d44184b8c9bc7ed45be9b1eea6a1554ca2
parent1eb414a370feb35205571568117a26248e074bb5
Remove a use of SFINAE in the Range constructor.

Summary:
Specifically, the constructor `implicit Range(Iter)` is now declared and defined for all `Range` specializations. It is an error to use it, and we `static_assert`, unless `Iter` is `char const *` or `char *`.

Performance effect
 ---
Measuring compilation-time on a file that just make ~40k StringPieces, compiled with -O3. All compilers produced identical code before/after this change.

* clang-trunk: 4% improvement
* gcc-5: no change
* gcc-4.9: 11% improvement
* gcc-7.1: 5% improvement

Could this possibly break any existing code?
 ---
Yes. If you have a function that's overloaded for both `Range<char const*>` and `Range<X>` and your input object is not `char const*` and is implicitly convertible to both `char const*` and `X`: that is now ambiguous whereas before it would unambiguously pick the `Range<char const*>` overload. I don't consider this scenario likely.

Why should this work?
 ---
Using SFINAE is more expensive at compile time (with some compilation environments) than not using it. It's necessary to use SFINAE when there is an alternative function which will be used in preference when the substitution fails, but when that is not the case it is on average cheaper to make the function always exist and use static_assert to disallow the bad uses of it. A bonus is that the caller gets a more comprehensible error message.

Reviewed By: nbronson

Differential Revision: D5639502

fbshipit-source-id: 13469f2995a487398734f86108087fdc8e32ad71
folly/Range.h