3

Let's start with this demo

#include <iostream>
using namespace std;

template <class T>
void abs(T number)
{
   if (number < 0)
        number = -number;
   cout << "The absolute value of the number is " << number << endl;
   return;
}

int main()
{
   int num1 = 1;
   int num2 = 2;
   double num3 = -2.1333;
   float num4 = -4.23f;

   abs(num1);
   abs(num2);
   abs(num3);
   abs(num4);

   return 0;
}

The output only showed num3 and num4 in its absolute value form. num1 and 2 were never displayed.

But doesn't program reads from top to bottom? I thought that if num1 is greater than 0, then it should, by all means, go to cout statement, and i.e., print 1.

It seems like this template function is omitting for those that are not negative in the beginning....

I tested without using the template function, and worked fine.

Thank you

CppLearner
  • 16,273
  • 32
  • 108
  • 163

4 Answers4

4

Get rid of the using namespace std .. it's providing a more specific function.

eduffy
  • 39,140
  • 13
  • 95
  • 92
  • Only that won't help though - better rename that abs() to something else :) – Shelwien Aug 04 '10 at 01:10
  • 1
    In particular - if `` is included it will declare `int std::abs(int)` and `long std::abs(long)`. `using namespace std;` is just pure evil and should be avoided at all costs. – D.Shawley Aug 04 '10 at 01:15
  • yes, thank you for the recommendation. :) mind was blank didn't remember abs was already a build-in function. – CppLearner Aug 04 '10 at 01:23
  • Plus `` could be included, which has `float` and `double` overloads of `abs`. – James McNellis Aug 04 '10 at 01:26
4

There is an abs function built-in to the standard library:

int abs ( int n );
long abs ( long n );

The compiler is going to use these versions in preference to your templated function since non-templated functions are more specific than templated functions, and thus take precedence in function overload resolution.

I recommend that you rename your abs function to something else to fix this.

As a side note, this might be questionable behavior on the part of your standard library implementation. It appears that #include <iostream> is pulling in a non-std-namespaced declaration of abs and it probably shouldn't be doing that. If you switch to C-style printfs then your program works fine without having to rename anything (at least on my platform, that is).

#include <stdio.h>

template <class T>
void abs(T number)
{
   if (number < 0)
        number = -number;
   printf("The absolute value of the number is %g\n", (double) number);
   return;
}

int main()
{
   int num1 = 1;
   int num2 = 2;
   double num3 = -2.1333;
   float num4 = -4.23f;

   abs(num1);
   abs(num2);
   abs(num3);
   abs(num4);

   return 0;
}

I don't recommend that as a solution, just as a curiosity.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • hahaha yes. This is right. In fact, when I was doing the debugging (without the t class), I was forced to change to the function name. It gave me error like old ambiguous abs(int x) , and it said overload. i realized that abs was causing the conflict, but didn't apply that suspect in this piece of code. thank you John! – CppLearner Aug 04 '10 at 01:15
  • it was stupid to not remember abs function in the standard library rofl – CppLearner Aug 04 '10 at 01:16
  • Some standard library implementations (e.g., the Microsoft C++ standard library) place the C standard library names in the global namespace, even when the `` header is included. – James McNellis Aug 04 '10 at 01:40
2

There is also a standard library function, std::abs, which is declared in <cstdlib> (int and long overloads) and <cmath> (float, double, and long double overloads).

<iostream> may include either of these headers. If it does, then the std::abs name is brought into the global namespace because of your use of using namespace std;

During overload resolution, if a nontemplate function has parameters of types that exactly match the types of the arguments, function templates of the same name will not be considered (and in general, nontemplate functions are preferred to function templates).

In your example, you say that your abs is being called for the two floating point values, but not for the integers. I would guess that your implementation is including <cstdlib> but not <cmath>.

You can remove the using namespace std; from your program, which should resolve the problem. Some implementations (e.g., Microsoft Visual C++) also place the C standard library names in the global namespace, so this may not work.

You can force your function template to be called by explicitly only allowing function templates to be matched during overload resolution:

abs<>(num1);

It is probably just easier to rename your function to something else.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
0

Introduce your own namespace

#include <iostream>
#include <cstdlib> // just for testing ADL of 'abs'

namespace ns // introduce namespace
{
  template<class T>
  void abs(T number)
  {
    if (number < 0)
    {
      number = -number;
    }

    std::cout << "The absolute value of the number is " << number << std::endl;
  }
}

int main()
{
  int num1 = 1;
  int num2 = 2;
  double num3 = -2.1333;
  float num4 = -4.23f;

  using ns::abs; // use abs from the namespace just introduced above

  abs(num1);
  abs(num2);
  abs(num3);
  abs(num4);

  return 0;
}
dubnde
  • 4,359
  • 9
  • 43
  • 63