Reputation:
As an example in Ruby (1.8)
i = 4
i.class => fixnum
i += 1.3
i.class => float
Can this be achieved in C++?
for instance
template<class T>
struct Number {};
Number<int> foo;
foo.changeTypeToFloat(); // <-- Possible?
// foo now Float?
Upvotes: 0
Views: 4909
Reputation: 33792
Nope you cant.
However you can have a very awkward solution involving union
/ overloading the =
operator which i haven't tried out. So i cant say it'll work.
Upvotes: 0
Reputation: 14148
What follows is a direct answer to the question, as asked. As comments on the question suggest, it would be interesting to know why you are asking it, i.e., what you are trying to achieve.
As Oli writes in his answer, C++ is statically typed so no, the type of a variable can't be changed at runtime.
However, if you know in advance the set of types you want for your variable (from your example int
and float
), you could declare a variable whose type is "int or float". This is the union
solution other answers allude to. However, union
s have their quirks and are pretty error-prone. Moreover, a union alone is usually not enough, as some information about the currently held type is usually necessary.
There comes Boost.Variant, which is a "discriminated union" (a union which "knows" what type it is currently holding). It allows you to write something like:
// Warning: off the top of my head, not compiled, less tested
boost::variant<int, float> int_or_float;
// Variants initialize by default as the first type in their list,
// so int_or_float is currently holding an int
assert(int_or_float.which() == 0);
int_or_float = 0.1;
// Now holding a float
assert(int_or_float.wich() == 1);
Upvotes: 0
Reputation: 506905
Like others say, in C++ this can't be done. The issue is not specific to class templates, though. But there are some workarounds that work in some scenarios.
You can use boost::variant<>
to do what you want
boost::variant<int, float> v;
v = 0; // v is now storing an int
v = 0.f; // v is now storing a float
struct A {
typedef void result_type;
void operator()(int i) const {
// process the int
}
void operator()(float f) const {
// process the float
}
};
// If v stores an int, it calls the int version.
// Otherwise it calls the float version.
boost::apply_visitor(A(), v);
See boost::variant.
You can use lexical scoping to make a new variable that hides the name of the other. This is usable when you just want the name to change its meaning, not necessarily the previous object. An important difference is that this changes things at compile time only. boost::variant
is able to track its stored type at runtime.
int i = 0; // i now refers to an int variable
{
float i = 0.f; // i now refers to a float variable
}
// i refers again to an int variable.
Hope it helps.
Upvotes: 3
Reputation: 25497
In C++, objects can't change their type at run time.
However, ere is a rough equivalent of a possibility
template<class T>
struct Number {
template<class U> operator U(){
U temp;
// conversion code typically using casts e.g.
return temp;
}
};
This lets you write code such as
template<class T>
struct A{
template<class U> operator U(){
return U();
}
};
int main(){
A<int> a1;
float f1 = a1; // convert a1 to float equivalent and so on.
A<float> f2 = a1; // convert a1 of type A<int> to A<float>
}
Upvotes: 1
Reputation: 272467
C++ is a statically-typed language. A variable has a fixed type. The best you can do at the language level is a conversion to a new variable, e.g.:
int i = 5;
float f = static_cast<float>(i);
Alternatively, you could write a variant class, and have the conversion handled internally. But this would really be syntactic sugar for the above.
Upvotes: 5