Я просто хочу вызвать эту функцию из imageproc
ящика. Прямо сейчас я делаю это так:
let mut contours = find_contours_with_threshold(&src_image.to_luma8(), 10);
И я продолжаю получать эту ошибку:
error[E0283]: type annotations needed
--> src/main.rs:77:24
|
77 | let mut contours = find_contours_with_threshold(&src_image.to_luma8(), 10);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `find_contours_with_threshold`
|
= note: cannot satisfy `_: Num`
note: required by a bound in `find_contours_with_threshold`
--> /home/mike/.cargo/registry/src/github.com-1ecc6299db9ec823/imageproc-0.23.0/src/contours.rs:61:8
|
61 | T: Num + NumCast + Copy + PartialEq + Eq,
| ^^^ required by this bound in `find_contours_with_threshold`
help: consider specifying the type argument in the function call
|
77 | let mut contours = find_contours_with_threshold::<T>(&src_image.to_luma8(), 10);
| +++++
Я понимаю, что ржавчина не может понять, чего ожидать в результате вызова этой функции. В документации он должен возвращать Vec<Contour<T>>
, где T: Num + NumCast + Copy + PartialEq + Eq
, но я не знаю, как перенести это в свой код.
Я пытался сделать это следующим образом: let mut contours: Vec<Contour<dyn Num + NumCast + Copy + PartialEq + Eq>> = find_contours_with_threshold(&src_image.to_luma8(), 10);
но я до сих пор не понимаю, что делаю, поэтому любая помощь будет отличной.
Это что-то вроде слишком большого количества значений для распаковки в python? я должен был сделать что-то вроде let x, y, z = find_contours..()
?
@KevinAnderson это действительно работает. Спасибо! Разве этот конкретный тип не должен быть из Num, NumCast, Copy, PartialEq, Eq
?
@Майк Num
, NumCast
, Copy
, ... это черты. Граница T: Num + NumCast + ...
означает, что тип T
должен иметь реализацию этих свойств. Один тип, удовлетворяющий такому ограничению, — это i32
, однако он не единственный. Сообщение компилятора означает, что он не может определить, какой тип вам нужен.
Существует параметр типа T
, который имеет некоторые границы характеристик (Num
, NumCast
и т. д.), и он не ограничен.
Конечно, это может быть i32
, но вы также можете определить собственный тип:
#[derive(Copy, Clone)]
struct MySillyNumber;
impl Num for MySillyNumber {}
// the rest of the required traits
и это такой же действительный тип для T
, как и i32
.
Вам нужно сообщить rustc, что такое T
. Вы можете сделать это несколькими способами:
find_contours_with_threshold::<i32>()
let x: Vec<Contour<i32>> = find_contours_with_threshold()
fn main() {
let x = find_contours_with_threshold();
foo(x);
}
fn foo(x: Vec<Contour<i32>>) {}
T
.Обратите внимание, что это отличается от использования Vec<Contour<dyn Num + ...>>
. Это превратит элементы в «объекты признаков», которые используют динамическую отправку (с виртуальной таблицей) для выполнения полиморфизма во время выполнения. Это, вероятно, не то, что вам нужно, в значительной степени потому, что dyn Trait
не имеет известного размера, а это означает, что он не может появиться в стеке без использования какого-либо указателя. И хотя Vec
, возможно, является интеллектуальным указателем, он требует, чтобы содержимое имело фиксированный размер, поскольку он полагается на это для индексации.
Спасибо @cameron1024 - Вы сформулировали это как ответ и с гораздо большей уверенностью, чем я в своем комментарии. Я ценю, как вы расширили различные типичные способы его указания. Для людей, пришедших с C++ (т.е. для меня), добавление типа шаблона к возвращаемому значению является распространенным шаблоном в Rust, но для меня это действительно странно, поскольку правила перегрузки функций C++ означают «да» для аргументов, но не для возвращаемых типов. Не то же самое, что конструкции, перегрузки и шаблоны, но тем не менее, мой мозг работает по умолчанию, поэтому такие вещи меня немного сбивают с толку.
ИМО, вывод типов в Rust на самом деле является чем-то вроде пушки для людей, плохо знакомых с языком. Не очевидно, почему что-то работает в одном фрагменте, а не в другом, и это может быть из-за единственного вызова функции на 100 строк ниже, которая обеспечивает конкретный тип. Без него язык был бы непригоден для использования, но он обеспечивает форму «действия на расстоянии», что наверняка может сбивать с толку.
Что произойдет, если вы используете
let mut contours = find_contours_with_threshold::<i32>(&src_image.to_luma8(), 10);
(или другой подходящий целочисленный тип)? Это работает? Я не знаком с этой библиотекой, но она запрашивает конкретный тип для вставкиContour
без ограничений.