I could not come up with a way to do this in C or Objective-C (take an expression and get its type). The typeof gcc extension would allow you to define a new type with the type of an expression, but that still doesn't help.
Using the sizes you can narrow it down, but it's not an "answer":
Code:
#include <stdio.h>
const char *type_string(int);
int main(int argc, char *argv[]) {
float f = 1.00;
short int i = 100;
long int l = 500L;
double d = 15.00;
printf("Size of f + i: %d\n",sizeof(f + i));
printf("Size of l / d: %d\n",sizeof(l / d));
printf("Size of i / l + f: %d\n",sizeof(i / l +f));
printf("Size of l * i: %d\n",sizeof(l * i));
printf("Size of f / 2: %d\n",sizeof(f / 2));
printf("Size of i / (d + f): %d\n",sizeof(i / (d + f)));
printf("Size of l / (i * 2.0): %d\n",sizeof(l / (i * 2.0)));
printf("Size of l + i / (double) l: %d\n",sizeof(l + i / (double) l));
printf("Type of f + i: %s\n",type_string(sizeof(f + i)));
printf("Type of l / d: %s\n",type_string(sizeof(l / d)));
printf("Type of i / l + f: %s\n",type_string(sizeof(i / l +f)));
printf("Type of l * i: %s\n",type_string(sizeof(l * i)));
printf("Type of f / 2: %s\n",type_string(sizeof(f / 2)));
printf("Type of i / (d + f): %s\n",type_string(sizeof(i / (d + f))));
printf("Type of l / (i * 2.0): %s\n",type_string(sizeof(l / (i * 2.0))));
printf("Type of l + i / (double) l: %s\n",type_string(sizeof(l + i / (double) l)));
return 0;
}
const char *type_string(int in) {
switch(in) {
default:
return "unknown type";
break;
case 1:
return "char";
break;
case 2:
return "short int";
break;
case 4:
return "float or int";
break;
case 8:
return "double or long int";
break;
case 12:
case 16:
return "long double";
break;
}
}
Note that i am only posting code because i don't think you are supposed to write code for this, but follow the implicit casting/promotion rules to solve this. The results of this program are ambiguous enough that it doesn't give it away for you.
Since C++ is more type-safe, and allows for overloading functions, you can do this there... I honestly can't say if the rules are the same in C and C++. There is enough else that is different between the two that i wouldn't bet my life on it, but i am pretty sure they are the same in this case. Anyhow, don't run this code unless you want the answers given away:
Code:
#include <iostream>
#include <string>
std::string myType(char);
std::string myType(short int);
std::string myType(int);
std::string myType(long int);
std::string myType(float);
std::string myType(double);
std::string myType(long double);
int main(int argc, char *argv) {
float f = 1.00;
short int i = 100;
long int l = 500L;
double d = 15.00;
std::cout <<"Type of f + i: " << myType(f + i) << std::endl;
std::cout <<"Type of l / d: "<<myType(l / d) << std::endl;
std::cout <<"Type of i / l + f: "<<myType(i / l +f) << std::endl;
std::cout <<"Type of l * i: "<<myType(l * i) << std::endl;
std::cout <<"Type of f / 2: "<<myType(f / 2) << std::endl;
std::cout <<"Type of i / (d + f): "<<myType(i / (d + f)) << std::endl;
std::cout <<"Type of l / (i * 2.0): "<<myType(l / (i * 2.0)) << std::endl;
std::cout <<"Type of l + i / (double) l: "<<myType(l + i / (double) l) << std::endl;
}
std::string myType(char in) {
std::string ret = "char";
return ret;
}
std::string myType(short int in) {
std::string ret = "short int";
return ret;
}
std::string myType(int in) {
std::string ret = "int";
return ret;
}
std::string myType(long int in) {
std::string ret = "long int";
return ret;
}
std::string myType(float in) {
std::string ret = "float";
return ret;
}
std::string myType(double in) {
std::string ret = "double";
return ret;
}
std::string myType(long double in) {
std::string ret = "long double";
return ret;
}
Since you can mix Objective-C and C++, I suppose you could get away with this. The formatting on my couts is a little sloppy, because i was just using s// somewhat haphazardly to turn printfs into couts. Again, I really don't think you are supposed to write code for this.
I tried to think of something goofy to do in C. I was thinking if there would be some way to get the pointer to the result of an expression (no such luck, at least in GCC), it could be cast to void *, then with some memcpy'ing, typecasting, and dependence on different memory representations of the same value as different types of the same width (double vs. long int, int vs. float) except for 0, one might be able to jury rig something. My attempts failed, but that doesn't mean this is impossible.
Your idea doesn't quite work out, because the primitives are not classes, so you can't have a generic primitive. For objects there is the option to do introspection at runtime, but there's no option for that sort of thing here. Since you can't overload methods in Objective-C (if you have the same method name, it must have the same argument types and return type), you can't write a class that emulates the C++ behavior above.
Someone may be more clever than I am and be able to figure out a way to handle this in plain C or Objective-C, but it is definitely impractical, and once more not likely to be what the author was hoping for.
-Lee