1

Background: While studying chapter 16 page 808 of C++ Primer 5th edition I found two type of compare function.

template <typename T>  int compare(const T& v1, const T& v2)
{
    if (v1 < v2) return -1;
    if (v2 < v1) return 1;
    return 0;
}

template <typename T> int compare(const T &v1, const T &v2)  
{  
    if (less<T>()(v1, v2)) return -1;  
    if (less<T>()(v2, v1)) return 1;  
    return 0;  
}  

The problem with our original version is that if a user calls it with two pointers and those pointers do not point to the same array, then our code is undefined.

This above line is not clear to me.
Can anyone explain this above line?

Mat
  • 202,337
  • 40
  • 393
  • 406
  • `int a[42] = {}; int b[12] = {}; int res = compare(&a[4], &b[5]);` is undefined for the first, implementation defined for the second. – Jarod42 Jul 18 '17 at 09:19
  • or, if the code were less type-safe, [Is comparing two void pointers to different objects defined in C++?](https://stackoverflow.com/questions/8225501/is-comparing-two-void-pointers-to-different-objects-defined-in-c) – underscore_d Jul 18 '17 at 09:22
  • I have checked code `int a[42] = {}; int b[12] = {}; int res = compare(&a[4], &b[5]);` it is working fine in linux. – Niraj Burnawal Jul 18 '17 at 09:25
  • 1
    "checked" how? If the behaviour is un(defined|specified), then the particular results you happen to get on any given compiler or run of the program don't matter at all. Such behaviour should not be allowed to occur, and its results when it does occur should not be relied upon. – underscore_d Jul 18 '17 at 09:25
  • Maybe this is a broader-scale duplicate of [Undefined, unspecified and implementation-defined behavior](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) or [What are all the common undefined behaviours that a C++ programmer should know about?](https://stackoverflow.com/questions/367633/what-are-all-the-common-undefined-behaviours-that-a-c-programmer-should-know-a) – underscore_d Jul 18 '17 at 09:27
  • Finally, I think this is really a duplicate of [Universal less<> for pointers in C++ standard](https://stackoverflow.com/questions/1098966/universal-less-for-pointers-in-c-standard) or [How do the operators < and > work with pointers?](https://stackoverflow.com/questions/4607418/how-do-the-operators-and-work-with-pointers) (sure, the questions are not exactly, but the answers are) – underscore_d Jul 18 '17 at 09:34

2 Answers2

1

The operators >, >=, < and <= invoke undefined behaviour when applied to pointers into different arrays, according to the C language standard, and inherited by the C++ language standard. It's a pain. (== and != don't have undefined behaviour if the pointers are valid, the only problem is that a pointer past the end of one object may compare equal to a pointer to the start of another object. For example int a, b and compare &a[1] and &b[0]).

The less() function doesn't have this problem. It has defined behaviour in those cases as well. It has defined behaviour because the C++ standard says so, and it is up to the implementor of the standard library to make it work. On most current implementations less() is just as efficient as < .

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • I thought all comparisons were undefined if they were between pointers falling within different objects. How does `less()` get more specified behaviour here? I _think_ I understand it for measuring the distance: iis allowed to form, if not dereference, a pointer to an imaginary element 1 past the end of an array, and each non-array object can be treated as an array of size 1 for this purpose, so one can increment the lower pointer until it compares `==` to the upper and return the count of increments. I assume `less()` relies on some clause that makes this possible, too. – underscore_d Jul 18 '17 at 09:29
  • Hmm, this seems to go into more depth: [How do the operators < and > work with pointers?](https://stackoverflow.com/questions/4607418/how-do-the-operators-and-work-with-pointers) – underscore_d Jul 18 '17 at 09:33
  • @underscore_d -- `std::less` for pointer types relies on the implementor's knowledge of the target hardware. It can't be implemented in portable C++, which is part of the reason that it's in the standard library. – Pete Becker Jul 18 '17 at 11:40
0

An array index can be specified via pointers.

An array is a series of consecutive storage locations. Therefore, for valid and arbitrary indexes x and y of an array will have only one of the following two relations among them:

x < y
y < x

Method 1 simply compared 2 values. Therefore, it can compare 2 arbitrary pointers as well. Hence, any 2 indexes(specified as pointers) of same array can be compared in a valid way. Hence, method one will give valid/correct/expected result if parameters are from same array.

If method 1 is used with any arbitrary pointers then user has to be aware of possible result given by the method.

sameerkn
  • 2,209
  • 1
  • 12
  • 13
  • This is unclear and only explains by omission why the 1st method cannot compare arbitrary pointers, and it doesn't explain why the 2nd one _can_. – underscore_d Jul 18 '17 at 10:44