Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Как проверить соответствие типов данных?


Автор: proc_maker 11.8.2010, 12:44
Вот написал такой вот кусочек кода, однако столкнулся с траблом проверки соответствия типов данных на этапе компиляции.

Например, использование var2_int должно вызывать ошибку компиляции поскольку тип переменной, возвращаемой ключем определен как double.

Подскажите плз чего бы наколдовать (я думаю в функции getValue() перед кастом);

Спасибо, 
Дмитрий



Код

#include <stdio.h>
#include <string.h>

class Base
{
public:
   Base(const char* const pName):
      mpName(pName)
   {
   }

   inline const char* getName() const
   {
      return mpName;
   }

private:
   const char* const mpName;
};

template<class T> class Value : public Base
{
public:
   explicit Value(const char* const pName, const T& value):
      Base(pName),
      mValue(value)
   {
   }

   const T& getValue() const
   {
      return mValue;
   }

private:
   const T mValue;
};

/* DO NOT CHANGE */
/* DO NOT CHANGE */const Base* const vars[] =
/* DO NOT CHANGE */{
/* DO NOT CHANGE */   new Value<int>("variable1", 123),
/* DO NOT CHANGE */   new Value<double>("variable2", 3.141592645),
/* DO NOT CHANGE */   new Value<char*>("variable3", "dima")
/* DO NOT CHANGE */};
/* DO NOT CHANGE */

template<class T> T getValue(const char* const pName)
{
   for (unsigned i = 0; sizeof vars / sizeof vars[0] > i; ++i)
   {
      const Base* const pVar = vars[i];
      if (0 == strcmp(pName, pVar->getName()))
      {
         const Value<T>* const pValue = static_cast<const Value<T>*>(pVar);
         return pValue->getValue();
      }
   }

   // тут у нас должен быть ексепшн
   return 0;
}

int main(int argc, char *argv[])
{
   int var1 = getValue<int>("variable1");           // Правильно
   printf("var1 = %d\n", var1);

   int var2_int = getValue<int>("variable2");    // НАДО ЧТОБЫ ВЫЗЫВАЛО ОШИБКУ КОМПИЛЯЦИИ
   printf("var2_int = %d\n", var2_int);

   double var2_double = getValue<double>("variable2");   // Правильно
   printf("var2_double = %f\n", var2_double);

   const char* const var3 = getValue<char*>("variable3");   // Правильно
   printf("var3 = %s\n", var3);

   return 0;
}


Автор: Earnest 11.8.2010, 14:24
Ничего ты тут с кастом не наколдуешь без дополнительной информации.
И вообще, налицо какие-то логические странности: с одной стороны, ты забиваешь в массив переменные различного типа по индексам, а при выборке хочешь получить конкретный тип по имени... Или массив заполняется просто для отладки?
Кроме того, такая форма, что шаблонный тип только в возвращаемом значении крайне неудобна - не сможешь ты написать double val = getValue ("bla-bla-bla").
Насколько я понимаю, задача состоит в том, чтобы сделать именованные переменные произвольного типа. Во-первых можно просто использовать boost::any (только добавить туда имя). Во-вторых, если хочешь собственный велосипед, нужно добавить информацию. Самый простой способ - хранить вместе со значением тэг типа. По ходу, как ты хочешь добывать значение, перебирая все переменные и приводя их к нужному типу, по другому и не получится, т.к. тип не динамический, а статик-каст тебе приведет... И вовсе не при компиляции тебе нужна проверка, а в рантайме - по крайней мере, так из кода следует.
Если бы при компиляции, то можно было нарисовать какие-нибудь доп. шаблонные классы свойств, но тогда так как у тебя - писать нельзя.

Автор: proc_maker 11.8.2010, 14:48
Надо сделать сохранение-восстановление настроек программы. Я привел пример для трех переменных разных типов, которые сохраняются в файле вида:

variable1 = 123
variable2 = 3.141592645
variable3 = dima

Очень не хочется чтобы клиентский код имел доступ к манипуляции с типами данных дабы избежать возможности написать что-либо похожее с var2_int, тоесть тупо перепутать тип данных. Если же и делать контроль в рантайме то все это должно быть напрочь скрыто внутри этой имплементации и недоступно клиенту.

Автор: Earnest 11.8.2010, 15:54
Еще раз повторю, если задача сугубо практическая, посмотри на boost::any, а не изобретай велосипед. При попытке извлечь не тот тип бросается исключение, его модно перехватить и рулить дальше. Чтобы закрыть от клиентского кода, оберни сверху своим классом. В компил-тайм можно проверить только константные выражения, причем точно известные именно в момент компиляции, а в твоей задаче это не так.

Автор: xvr 12.8.2010, 13:36
Цитата(proc_maker @  11.8.2010,  12:44 Найти цитируемый пост)
Например, использование var2_int должно вызывать ошибку компиляции поскольку тип переменной, возвращаемой ключем определен как double.

Earnest совершенно права - сделать это compile time в принципе невозможно, только run time

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)