Проверка типов во время компиляции C

#c #templates #casting

#c #шаблоны #Кастинг

Вопрос:

Я создал список типов. Затем я создаю класс, используя шаблон, передающий список типов. Когда я вызываю функцию print класса с некоторыми не указанными типами, они преобразуются. Как я могу обеспечить соблюдение точного типа во время компиляции? Итак, если я использую тип, не указанный в списке, я получаю ошибку компилятора. Спасибо.

 template <class T, class U>
struct Typelist
{
   typedef T Head;
   typedef U Tail;
};


class NullType
{
};

typedef Typelist<int,Typelist<float,Typelist<char*,NullType> > > UsableTypes;

template<class T>
class MyClass
{
    public:
    void print(T::Head _Value) { std::cout << _Value; }
    void print(T::Tail::Head _Value) { std::cout << _Value; }
    void print(T::Tail::Tail::Head _Value) { std::cout << _Value; }
    private:
};


MyClass<UsableTypes> testclass;

void TestMyClass()
{
    int int_val = 100000;
    float flt_val = 0.1f;
    char* char_val = "Hi";
    short short_val = 10;
    std::string str_val = "Hello";

    testclass.print( int_val ); // OK  8-)
    std::cout << endl;
    testclass.print( flt_val ); // OK  8-)
    std::cout << endl;
    testclass.print( char_val ); // OK  8-)
    std::cout << endl;
    testclass.print( short_val); // this compiles OK and works ???  8-(
    std::cout << endl;
    testclass.print( str_val ); // compile error  8-)
    std::cout << endl;
}
  

@Kerrek SB: Привет, я думал, это поможет мне со следующим шагом, который заключался в создании функции печати в зависимости от содержимого t_list, типов и количества типов. Но я изо всех сил пытаюсь разделить обработку во время компиляции и обработку во время выполнения. Что я пытаюсь сделать, так это создать функцию печати для каждого типа в списке. Итак, если список имеет два типа, будут созданы две функции печати, а если типов пять, то будут созданы пять функций печати, по одной для каждого типа.
Когда я делаю это:

  typedef Typelist<int,Typelist<float,Typelist<char*,NullType> > > UsableTypes;

 MyClass<UsableTypes> newclass
  

Создает ли это три экземпляра MyClass по одному для каждого типа в списке или создает один экземпляр, и я должен создать функцию печати для каждого типа?
Я чувствую, что у меня почти все блоки в голове, но просто не могу соединить их вместе. Любая помощь, которую вы можете предложить, будет принята с благодарностью. Спасибо.

Комментарии:

1. Ваша print функция не очень полезна, поскольку она не реализует какой-либо вид рекурсии.

Ответ №1:

Добавьте шаблон частной функции

 template<typename T> void print(T);
  

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

Комментарии:

1. Спасибо, что решили мою проблему. Это кажется очевидным, когда указано 🙂

Ответ №2:

Вам пришлось бы превратить вашу print функцию в шаблон, а затем проверить, совпадают ли типы:

 template <typename U>
void print(const U amp; u)
{
  // use std::is_same<typename std::decay<T::Head>::type, typename std::decay<U>::type>::value
}
  

Здесь я ворую is_same и decay из <type_traits> , но если у вас нет C 11, вы можете либо взять их из TR1 или Boost, либо просто написать их самостоятельно, поскольку это очень простые классы-модификаторы типа.

Условное обозначение лучше всего использовать в static_assert , что является еще одной особенностью C 11, но для C 98/03 существуют аналогичные конструкции, которые при определенных условиях приводят к ошибке во время компиляции.

Комментарии:

1. @sehe: это действительно встречалось на моем пути раньше 🙂

2. Спасибо, это помогло мне с моей следующей проблемой, заставив создавать функции печати для списков типов различного размера.

Ответ №3:

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

Комментарии:

1. Спасибо, теперь я начинаю смотреть на эти проблемы под другим углом.