2

std::sort has complexity requirements, which is O(n log n). Besides common QuickSort or IntroSort, other algorithms would fit it.

Sure Bubble Sort with O(n2) does not fit.

However, if we take a specialization for pointers to int without explicit predicate. The number of iterations or comparisons cannot be observed, as there's no way to specialize operator< or pointer indirection, and user's code is not allowed to specialize std::less for ints, and as the predicate isn't passed, it is std::less/operator<.

So can int* predicate-less version be specialized to use Bubble Sort by some evil implementation of the STL?

This question is similar to Would it be legal to implement overloads of std::sort with radix sort?, but the answer points out that the Radix sort meets the requirements, so it is not what I intend to ask.


The actual intention is if the implementation is allowed to do optimizations, that are worse for complexity, but better for runtime. I want to focus on "if this is allowed" rather than "if this is possible to make faster implementation with worse complexity", that's why I picked Bubble Sort as clearly horrible example.

Alex Guteniev
  • 12,039
  • 2
  • 34
  • 79
  • 2
    `user's code is not allowed to specialize std::less`. User's code is indeed allowed to specialize `std::less`, just not for built-in types. Other than that, I fail to see the point of the question. – SergeyA Nov 15 '21 at 19:19
  • 2
    What is the background for this question? Is there an underlying problem, or is it plain curiosity? Even if for curiosity, would you mind elaborating on the background and your thoughts? And if it's an underlying actual problem, please ask about it directly instead. – Some programmer dude Nov 15 '21 at 19:25
  • 3
    Would it be fair to summarize this question as "The as-if rule allows a compiler to make performance improvements as long as they don't change observable effects, but does it also permit a hypothetical hostile-but-conforming compiler to make performance degradations as long as they don't change observable effects"? – Nathan Pierson Nov 15 '21 at 19:28
  • 1
    @Someprogrammerdude, the intent is to clarify if an implementation is allowed to do useful but technically violating the requirements optimization, like worse complexity but better runtime, if the results are not observable. I used Bubble Sort as clearly hostile example to focus the question on "if it is allowed" rather than "if there can be such optimizations" – Alex Guteniev Nov 15 '21 at 19:33
  • 1
    This all, question and the phrasing of some comments, reminds me of the old paper [reflections on trusting trust](https://www.win.tue.nl/~aeb/linux/hh/thompson/trust.html). – Some programmer dude Nov 15 '21 at 19:37
  • @NathanPierson, yes – Alex Guteniev Nov 15 '21 at 20:02
  • 2
    To meets requirements, `sort` can still do `if (std::distance(begin, end) < some_fixed_threshold) bogobogo_sort(begin, end);else nlogn_sort(begin, end);`. – Jarod42 Nov 15 '21 at 23:01

1 Answers1

3

The number of iterations or comparisons cannot be observed

So? The complexity of algorithms is given by the Standard, not some observer. Whether you can observe such complexity is irrelevant.

25.8.2.1

  1. Complexity: Let N be last - first. O(NlogN) comparisons and projections.

That's pretty clear. On the other hand, bubble sort requires O(n^2), therefore if an implementation were to use Bubble sort, it would not be conforming to the Standard.

I fail to see how as-if rule is relevant at all.

Also note there are overloads with custom Compare functor, in that case the number of comparison can be observed, even for primitive types.

The actual intention is if the implementation is allowed to do optimizations, that are worse for complexity, but better for runtime.

No, the upper bound for std::sort is clear as I stated above. But if through some magic, the compiler can sort in O(1) or not use Compare, it by all means can do that. If the compiler can prove that you cannot observe whether std::sort has been called or not, the as-if rule can kick in here. Very theoretically, if you use std::sort to only find and access the minimum element, the compiler is under this rule allowed to use a simple for loop finding the maximum.

Quimby
  • 17,735
  • 4
  • 35
  • 55
  • 2
    _I fail to see how as-if rule is relevant at all_ [conforming implementations are required to emulate **(only)** the observable behavior of the abstract machine](https://timsong-cpp.github.io/cppwp/n4868/intro.abstract#1.sentence-4). – Language Lawyer Nov 15 '21 at 21:10
  • 2
    Specifically, is the number of integer comparisons observable? The number of comparisons of UDTs is observable because you could add `++number_of_comparisons;` to your implementation of `operator<`. But you cannot overload `operator<(int, int)`. Does that make integer comparisons non-observable? Does this fall under "quality of implementation"? – Raymond Chen Nov 15 '21 at 21:16
  • @LanguageLawyer That's convincing, still this would throw all complexities out of a window unless you explicitly checked them at runtime and printed them. Surely that cannot be what's intended. – Quimby Nov 15 '21 at 21:25
  • @RaymondChen I guess it does, but as I said above, this would mean that if you don't check them explicitly, is `std::sort` allowed to use `std::next_perm` and `std::is_sorted` for sorting? Even for simple `vec vec={...}; sort(vec.begin(),vec.end());` just because there is not `number_of_comparisons`? – Quimby Nov 15 '21 at 21:28
  • 3
    @Quimby I think, from a language-lawyer point of view, that an implementation is permitted to pessimize code in an unobservable way. For example, it could add `sleep(exp(2, n))`, since that doesn't change the number of comparisons. However, such an implementation is unlikely to be popular. The standard leaves many things to "quality of implementation" meaning "We are not going to require that the implementor does a good job, but we hope that implementors are motivated to do a good job anyway. If an implementation is bad, people will stop using it." – Raymond Chen Nov 15 '21 at 23:09