Defining multiple functions with the same name using custom types

181 views Asked by At

I've been playing around with C++ and I've noticed something that I don't quite understand:

typedef float degrees;
typedef float radians;

void my_func(degrees n);
void my_func(radians m);

Declaring a function like this, I get a warning that the function is re-declared as if they are identical. Does this mean, when looking at function definitions, the compiler only sees built-in types and doesn't care about custom defined types, and since they're bot floats, it just considers them to be the same function?...

If that's the case, how do I get around this? Do I just have to make a different function?

4

There are 4 answers

0
Nathan Pierson On BEST ANSWER

Another possibility is to define Radian and Degree classes to have an explicit conversion from floats and an implicit conversion to them.

class Radian{
    float m_value;
public:
    explicit Radian(float t_value) : m_value(t_value) { }
    operator float() const { return m_value; }
};

class Degree{
    float m_value;
public:
    explicit Degree(float t_value) : m_value(t_value) { }
    operator float() const { return m_value; }
};

void my_func(Radian r);
void my_func(Degree d);

my_func(Radian(10)); // calls the Radian overload
my_func(Degree(10)); // calls the Degree overload
my_func(10); // Doesn't call either because both ctors are explicit


The implicit conversions to float mean that you can pass a variable of type Radian or Degree to a function expecting float and it'll just work.


This version does mean that, unlike the typedefs, you won't be able to write things like

Degree alpha = 30;
Degree beta = 60;
Degree gamma = alpha + beta; // 90 degrees

However, if you want, you can also define arithmetic operators like operator+, operator*, etc for each class. For instance, you might want to always perform Degree arithmetic modulo 360, so that 180 + 180 = 0.

0
Cosmin Petolea On

typedef only creates a new name for an already existing type, so the compiler associates degrees, radians and float as being the same data type, in your example. They are not custom types per say, rather just a new name for a pre-existing type.

0
Zig Razor On

The problem is that you are not using 2 different types but only 2 different alias to the same type, so for the compiler it's the same function.

Now the workaround are multiple:

The first one can be declare 2 different classes with only an attribute of type float, and if you want a implicit conversion to float of the double reimplement the conversion in this way:

class Radian{
public:
  float angle;
  Radian(){};
  operator float() { return angle; }
};

Another solution can be declare 2 different functions name for example:

void my_func_deg(degrees n);
void my_func_rad(radians m);

or create 2 different classes with an internal function:

 class Radian{
public:
  double angle;
  Radian(){};
  void my_func();
};
0
Aref Sayareh On

you can define classes to handle these problems. look this example:

class Degree{
public:
  double angle;
  Degree(){}
  void my_func(){
    // do some job
  }
};

class Radian{
public:
  double angle;
  Radian(){}
  void my_func(){
    // do some job
  }
};

int main(){
  Degree deg;
  Radian rad;

  deg.my_func();
  rad.my_func();
}

now they do different tasks in their functions.

OR if you don't want to make objects, you can make a static function in these classes.

class Radian{
public:

  static void my_func(float radian){
    // do some job
  }
};

typedef float degrees;
typedef float radians;

int main(){
  radians rad;

  Radian::my_func(rad)
}