Изменить тип класса шаблона - PullRequest
0 голосов
/ 01 ноября 2010

В качестве примера в 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 ]

5 голосов
/ 01 ноября 2010

C ++ - статически типизированный язык. Переменная имеет фиксированный тип. Лучшее, что вы можете сделать на уровне языка - это преобразование в новую переменную, например ::10000

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

В качестве альтернативы, вы можете написать вариант класса, и преобразование будет обработано внутри. Но это действительно было бы синтаксическим сахаром для всего вышеперечисленного.

3 голосов
/ 01 ноября 2010

Как говорят другие, в 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 может отслеживать его сохраненный тип во время выполнения.

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.

Надеюсь, это поможет.

1 голос
/ 01 ноября 2010

В C ++ объекты не могут изменять свой тип во время выполнения.

Однако, это грубый эквивалент возможности

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>
}
0 голосов
/ 01 ноября 2010

Далее следует прямой ответ на вопрос, как задано.Как показывают комментарии к вопросу, было бы интересно узнать, почему вы спрашиваете об этом, то есть чего вы пытаетесь достичь.

Как пишет Оли в своем ответе, C ++ имеет статическую типизацию, поэтому нет, типпеременной нельзя изменить во время выполнения.

Однако, если вы заранее знаете набор типов, которые вы хотите для своей переменной (из вашего примера int и float), вы можете объявитьпеременная, тип которой "int or 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);
0 голосов
/ 01 ноября 2010

Нет, вы не можете.

Однако у вас может быть очень неловкое решение, включающее union / перегрузку оператора =, которое я не пробовал. Так что я не могу сказать, что это сработает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...