更改模板类的类型

时间:2010-11-01 11:37:17

标签: c++ templates types

作为Ruby(1.8)的一个例子

i = 4
i.class => fixnum

i += 1.3
i.class => float

这可以用C ++实现吗?

例如

template<class T>
struct Number {};

Number<int> foo;

foo.changeTypeToFloat(); // <-- Possible?

// foo now Float?

5 个答案:

答案 0 :(得分:5)

C ++是一种静态类型的语言。变量具有固定类型。您在语言级别可以做的最好的事情是转换为新变量,例如:

int i = 5;
float f = static_cast<float>(i);

或者,您可以编写变体类,并在内部处理转换。但对于上述情况,这确实是语法糖。

答案 1 :(得分:3)

像其他人说的那样,在C ++中,这是无法做到的。但问题不是特定于类模板。但是有些解决方法在某些情况下有效。


您可以使用boost::variant<>做您想做的事情

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);

请参阅boost::variant


您可以使用词法作用域来创建一个隐藏另一个名称的新变量。当您只希望名称更改其含义时,这可用,而不一定是前一个对象。一个重要的区别是,这只会在编译时改变一些事情。 boost::variant能够在运行时跟踪其存储的类型。

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.

希望它有所帮助。

答案 2 :(得分:1)

在C ++中,对象无法在运行时更改其类型。

然而,ere大致相当于一种可能性

template<class T> 
struct Number {
   template<class U> operator U(){
      U temp;
      // conversion code typically using casts e.g.
      return temp;
   }
};

这使您可以编写

等代码
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>
}

答案 3 :(得分:0)

不,你不能。

但是你可能有一个非常尴尬的解决方案涉及union /重载=运算符,我还没有尝试过。所以我不能说它会起作用。

答案 4 :(得分:0)

以下是问题的直接答案。正如对这个问题的评论所表明的那样,知道你为什么要问它,即你想要达到的目标,这将是很有趣的。

正如Oli在他的回答中所写,C ++是静态类型的,所以不,变量的类型不能在运行时更改。

但是,如果您事先知道变量所需的类型集(来自示例intfloat),则可以声明类型为“int或float”的变量。这是其他答案提到的union解决方案。但是,union有他们的怪癖并且非常容易出错。此外,仅靠联合通常是不够的,因为通常需要一些关于当前持有类型的信息。

来了Boost.Variant,这是一个“有区别的联盟”(一个“知道”它目前持有什么类型的联盟)。它允许你写一些类似的东西:

// 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);