views:

168

answers:

3

Why can't I compile the program 1 when the the program 2 is working fine ? Why is it's behavior different?

Program 1:

#include <iostream>
typedef int s1;
typedef int s2;

void print(s1 a){ std::cout << "s1\n"; }
void print(s2 a){ std::cout << "s2\n"; }

int main() {
        s1 a;
        s2 b;

        print(a);
        print(b);

        return 0;
}

Program 2:

#include <iostream>
typedef struct{int a;} s1;
typedef struct{int a;} s2;

void print(s1 a){ std::cout << "s1\n"; }
void print(s2 a){ std::cout << "s2\n"; }
int main() {
        s1 a;
        s2 b;

        print(a);
        print(b);

        return 0;
}

This is a bug reproduce from templated class, How can I verify if two template argument are from the same type (in the case of the program 1)

A: 

int is a primitive type: no matter where you use it, it will always refer to exactly the same thing - an int.

struct{int a;} is not a primitive type - each time you define a struct{int a;}, you're creating a new type - hence why s1 and s2 are considered distinct in your Program 2 case.

For instance, consider the following:

typedef struct{int count;} apples;
typedef struct{int count;} airplanes;

Are apples and airplanes the same thing? Probably not. But their counts are both numerical counts. Hence why int is consistent but structs are not - int has no context associated with it, structs do.

typedef doesn't actually make any new types - it only aliases a type under another name.

Therefore, the difference between Program 1 and Program 2 is that in Program 1, you're attempting to define two versions of a function with (as far as the compiler is concerned) exactly the same signature: print(int). In Program 2, you're defining two different signatures: print([first struct type]) and print([second struct type]).

Amber
+6  A: 

Typedefs don't define new types, they merely create aliases for existing types. In your first program s1 and s2 are both aliases for int. In your second program they are aliases for two different structures that just happen to be identical in structure.

You could have assigned names to the two structures which would have made this clearer:

// Semantically identical to program 2
typedef struct a {int a;} s1;
typedef struct b {int a;} s2;

On the other hand if you made them aliases for the same type then the second program would fail just like the first:

// Different from program 2. This will draw a compile error.
struct s {int a;};
typedef struct s s1;
typedef struct s s2;
John Kugelman
A: 

The difference is that in program 1, s1 and s2 are aliases of the same type, whereas in program 2 they're different types. You can't define two overloads of a function with the same signature, even if you use different type names to produce that signature.

Wyzard