Как я могу сопоставить значение с типом в Rust?

#rust #type-conversion

Вопрос:

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

 my_programme u32
 

…и в моем коде у меня есть:

 match cli_type
{
   "u32" =>
   {
       my_generic_function::<u32>(args);
   },
   "u16" =>
   ...
 

Если я хочу сделать это для 8, 16, 32 и 64-разрядных целых чисел, как со знаком, так и без знака, это много вызовов my_generic_function() . Это выглядит грязно и кажется ненужным.

Могу ли я определить сопоставление между amp;str String значениями или и типом T или написать функцию , возвращающую тип T , чтобы вместо оператора соответствия я мог просто написать:

 my_generic_function::<get_type(cli_type)>(args);
 

Ответ №1:

Rust не хранит никакой информации о типе во время выполнения. В стандартной библиотеке есть функция std::any::type_name , которая может дать вам имя типа , но это всего лишь строка, и нет никакого способа вернуться в мир типов. Все это происходит во время компиляции и не может быть изменено позже.

Однако вы можете сохранить некоторый код с помощью макроса:

 macro_rules! make_call_typed {
   ($($t: ty),*) => {
       fn call_typed(input: amp;str, args: amp;str) {
           match input {
               $(
                   stringify!($t) => {
                       my_generic_function::<$t>(args);
                   }
               ),*
               other => panic!("unexpected type: {}", other)
           }
        }
    }
}
 

Когда ты называешь это так:

 make_call_typed!(u32, u16, i32, i16);
 

Он будет генерировать код, подобный этому:

 fn call_typed(input: amp;str, args: amp;str) {
    match input {
        "u32" => {
            my_generic_function::<u32>(args);
        }
        "u16" => {
            my_generic_function::<u16>(args);
        }
        "i32" => {
            my_generic_function::<i32>(args);
        }
        "i16" => {
            my_generic_function::<i16>(args);
        }
        other => panic!("unexpected type: {}", other),
    }
}