-1

I am trying to check if two characters are neighbours in a larger string but cant check the absolute value of the difference in their indices. Below is my code:

string state_string = "012345";
string goal_state_string = "125430";
for (int i = 0; i < state_string.length() - 1; i++)
{
    cout << abs(goal_state_string.find(state_string[i]) - goal_state_string.find(state_string[i + 1])) << endl;
}

and when I run I get the following output:

$ make test
g++ -std=c++11 test.cpp
test.cpp: In function ‘int main()’:
test.cpp:107:106: error: call of overloaded ‘abs(std::basic_string<char>::size_type)’ is ambiguous
         cout << abs(goal_state_string.find(state_string[i]) - goal_state_string.find(state_string[i + 1])) << endl;
                                                                                                          ^
In file included from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/cstdlib:75:0,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ext/string_conversions.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/basic_string.h:6349,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/string:52,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/locale_classes.h:40,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/ios_base.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ios:42,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ostream:38,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/iostream:39,
                 from test.cpp:1:
/usr/include/stdlib.h:70:5: note: candidate: int abs(int)
 int abs (int);
     ^~~
In file included from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/cstdlib:77:0,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ext/string_conversions.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/basic_string.h:6349,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/string:52,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/locale_classes.h:40,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/ios_base.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ios:42,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ostream:38,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/iostream:39,
                 from test.cpp:1:
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:56:3: note: candidate: long int std::abs(long int)
   abs(long __i) { return __builtin_labs(__i); }
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:61:3: note: candidate: long long int std::abs(long long int)
   abs(long long __x) { return __builtin_llabs (__x); }
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:70:3: note: candidate: constexpr double std::abs(double)
   abs(double __x)
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:74:3: note: candidate: constexpr float std::abs(float)
   abs(float __x)
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:78:3: note: candidate: constexpr long double std::abs(long double)
   abs(long double __x)
   ^~~
make: *** [Makefile:37: test] Error 1

hp user@DESKTOP-PGC8V9D /cygdrive/e/Google Drive/Phd_git/psvn/core/lessons/A-star
$ make test
g++ -std=c++11 test.cpp
test.cpp: In function ‘int main()’:
test.cpp:13:106: error: call of overloaded ‘abs(std::basic_string<char>::size_type)’ is ambiguous
         cout << abs(goal_state_string.find(state_string[i]) - goal_state_string.find(state_string[i + 1])) << endl;
                                                                                                          ^
In file included from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/cstdlib:75:0,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ext/string_conversions.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/basic_string.h:6349,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/string:52,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/locale_classes.h:40,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/ios_base.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ios:42,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ostream:38,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/iostream:39,
                 from test.cpp:1:
/usr/include/stdlib.h:70:5: note: candidate: int abs(int)
 int abs (int);
     ^~~
In file included from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/cstdlib:77:0,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ext/string_conversions.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/basic_string.h:6349,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/string:52,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/locale_classes.h:40,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/ios_base.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ios:42,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ostream:38,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/iostream:39,
                 from test.cpp:1:
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:56:3: note: candidate: long int std::abs(long int)
   abs(long __i) { return __builtin_labs(__i); }
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:61:3: note: candidate: long long int std::abs(long long int)
   abs(long long __x) { return __builtin_llabs (__x); }
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:70:3: note: candidate: constexpr double std::abs(double)
   abs(double __x)
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:74:3: note: candidate: constexpr float std::abs(float)
   abs(float __x)
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:78:3: note: candidate: constexpr long double std::abs(long double)
   abs(long double __x)
   ^~~
make: *** [Makefile:37: test] Error 1

My questions are as follows:

  1. shouldnt find the find function be returning some kind of integer type ie. an unsigned int and if so why doesnt it ie. what is the point of having this alternate type that doesnt seem to work for most function calls for which it should?
  2. what is best practise when working with this type/avoiding this problem? Should I cast it to an int?
Teererai Marange
  • 2,044
  • 4
  • 32
  • 50
  • 4
    As you see in compiler output, `abs` is defined for signed types. `std::string::size_type` is unsigned. To correctly find the distance between two unsigned values, first determine which one of them is the greatest and then subtract the other from it. – bipll Oct 09 '18 at 01:08
  • 1
    I had previously posted an answer, but I now see that the main caveats of your approach it that if [find](http://www.cplusplus.com/reference/string/string/find/) cannot retrieve the searched string, it returns [`std::string::npos`](http://www.cplusplus.com/reference/string/string/npos/), which is `-1`, that for an unsigned value means the biggest rappresentabile value. Once you handle that problem, you can find how to make the difference between two unsigned integers in this [code review's post](https://codereview.stackexchange.com/questions/51179/absolute-difference-function-for-stdsize-t) – Antonio Oct 09 '18 at 01:36
  • Also see [Is std::abs(0u) ill-formed?](https://stackoverflow.com/q/29750946/1708801) – Shafik Yaghmour Oct 09 '18 at 01:57

1 Answers1

1

To understand what does abs do, we must understand what's the difference between signed and unsigned type.

Consoder following statements:

a = 10
b = -20
c = a + b

does result of c depends on whether a,b,c is signed or unsigned ?

Surprisingly it doesn't. because computer handle numbers using two's complement, so if 2 numbers are separated by 2^N, they are considered the same number.

And not only add,subtract doesn't care about sign, multiplication also doesn't care about sign:

x*(2^N - y) = x*2^N - x*(-y) = x*(-y) mod 2^N

Because of such affect, restriction between signed and unsigned numbers is loosen.

The more details can be find in the instruction set of X86 architecture. Actually X86 defines an uniform add, which handles both signed and unsigned add, the only difference between signed and unsigned add is the carrier bit (also be called overflow/underflow bit).

And there are operators that do care about sign. like

  1. print. people are surely prefer -1 than 4294967295, so printf has separated symbol for signed and unsigned "%u"
  2. compare. 4294967295 > 0, but -1 < 0
  3. abs function
  4. and more on ...

When using operators who care about sign, you'd better be more careful. That's why abs is not allowed to take unsigned parameter.

Zang MingJie
  • 5,164
  • 1
  • 14
  • 27
  • 1
    Now I've never worked on a target that doesn't, but C++ does not require two's compliment for signed integers. It is simply the most commonly used solution for the problem. – user4581301 Oct 09 '18 at 03:34
  • Actually it makes no sense to put an unsigned value into abs. Because it will always be the same after it, because it is positive. And like @user4581301 pointed out overflow is undefined behavior, even if the target platform implemented it as two's complement. The compiler doesn't have to comply and can optimize weird things. – birdfreeyahoo Oct 09 '18 at 03:35