2014-09-25 5 views
3

Я хочу проверить коды возврата API-интерфейсов C в общем виде, и результат должен быть свободен от типов C, таких как libc::c_int. Существуют ли какие-либо способы, чтобы написать функцию, какКак нарисовать общие типы, которые, как я знаю, являются целыми числами?

fn check<S: PartialOrd + std::num::Zero, T> (x: S) -> Option<T> { 
    if std::num::zero::<S>() <= x { Some(x as T) } 
    else { None } 
} 

, когда я уверен, что S и T являются неотъемлемым типом для всех использований check()? Компилятор отвергает мой код жалуясь error: non-scalar cast: `S` as `T`

ответ

4

Изменены для Rust 1.x

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

extern crate num; 

use num::{Zero, NumCast}; 

fn check<S: PartialOrd+Zero+NumCast, T: NumCast>(x: S) -> Option<T> { 
    if x >= S::zero() { Some(num::cast(x).unwrap()) } 
    else { None } 
} 

fn main() { 
    let x: i8 = 10; 
    let y: Option<i32> = check(x); 
    println!("{:?}", y); 

    let x: i8 = -10; 
    let y: Option<i32> = check(x); 
    println!("{:?}", y); 
} 

Здесь я использую специальный признак, num::traits::NumCast от num обрешетки, которая реализуется для всех примитивных типов и обеспечивает статический метод, который преобразует эти типы из ничего, реализующего num::ToPrimitive. num Ящик также предоставляет функцию, num::cast(), которая дает простой интерфейс для выполнения числовых операций.

Отметьте, что cast(x)Option<T>; он возвращает None, если x не может быть представлено в целевом типе. Я использую unwrap() здесь, потому что в вашем случае, согласно вашему описанию, невозможность правильно преобразовать значение, скорее всего, является ошибкой программирования, поэтому выполнение задачи кажется более уместным. Также можно написать cast(x) непосредственно:

if x >= S::zero() { num::cast(x) } 
... 

В этом случае check() вернется None не только тогда, когда ее аргумент является отрицательным, но если это невозможно преобразовать аргумент типа результата.

+0

Это именно то, что я искал! – nodakai

+0

К сожалению, больше нет указателя 'std :: num :: NumCast' или' ToPrimitive', и я не уверен, что они были заменены чем-либо. Вещи имеют довольно значительные изменения – Ponkadoodle

+0

@Wallacoloo, действительно, большинство числовых признаков были удалены из 'std'. Некоторые из них, в том числе связанные с преобразованиями, были перенесены в ящик 'num'. Я скоро обновлю ответ. –