讓我們考慮一個這樣的函式:
fn test<const N: usize>() -> [f64; N] {
if N == 1 {
[0.0_f64; 1]
} else if N == 2 {
[1.0_f64; 2]
} else {
panic!()
}
}
我的理解是編譯器會N在編譯時評估 的值。如果是這種情況,if也可以在編譯時評估該陳述句,因此應該回傳正確的型別,因為[0.0_f64; 1]僅回傳 ifN == 1并且[1.0_f64; 2]僅回傳 if N == 2。
現在,當我嘗試編譯這段代碼時,編譯器失敗了,基本上告訴我回傳陣列的維度是錯誤的,因為它們沒有明確N的長度。
我確實意識到,我可以將這個特定示例實作為
fn test<const N: usize>() -> [f64; N] {
match N {
1 => { [0.0_f64; N] },
2 => { [1.0_f64; N] },
_ => { panic!("Invalid value {}", N) },
}
}
但這在我的實際代碼中不起作用,因為它為不同的分支使用具有固定陣列大小的不同函式。
有沒有辦法做到這一點?也許使用像#![cfg]makro這樣的東西?
為了澄清我為什么我的問題不起作用,讓我們寫出來:
fn some_fct() -> [f64; 1] {
[0.0_f64; 1]
}
fn some_other_fct() -> [f64; 2] {
[1.0_f64; 2]
}
fn test<const N: usize>() -> [f64; N] {
match N {
1 => some_fct(),
2 => some_other_fct(),
_ => {
panic!("Invalid value {}", N)
}
}
}
由于程式結構中的其他限制,我無法真正撰寫some_fct()并some_other_fct()回傳通用尺寸。
uj5u.com熱心網友回復:
您可以使用通用特征來做到這一點:
trait Test<const N: usize> {
fn test() -> [f64; N];
}
然后你為一個零大小的型別實作它:
struct T;
impl Test<1> for T {
fn test() -> [f64; 1] {
return [0.0_f64; 1];
}
}
impl Test<2> for T {
fn test() -> [f64; 2] {
return [1.0_f64; 2];
}
}
缺點是呼叫有點麻煩:
fn main() {
dbg!(<T as Test<1>>::test());
dbg!(<T as Test<2>>::test());
}
但正如下面的@eggyal 評論,您可以添加一個具有良好撰寫系結的通用函式來獲得您所需的語法:
fn test<const N: usize>() -> [f64; N]
where
T: Test<N>
{
T::test()
}
fn main() {
dbg!(test::<1>());
dbg!(test::<2>());
}
現在,您沒有“panic!使用錯誤時”的行為N。考慮一個特性而不是限制:如果你使用錯誤,N你的代碼將無法編譯而不是在運行時出現恐慌。
如果你真的想要這種panic!()行為,你可以使用不穩定的特性來獲得它#![feature(specialization)],只需添加default到這個 impl 中:
impl<const N: usize> Test<N> for T {
default fn test() -> [f64; N] {
panic!();
}
}
但是該功能被明確標記為不完整,所以我還不能指望它。
uj5u.com熱心網友回復:
這是一個不是特別聰明,但易于理解并且類似于原始解決方案的解決方案:
fn test<const N: usize>() -> [f64; N] {
match N {
1 => some_fct().as_slice().try_into().unwrap(),
2 => some_other_fct().as_slice().try_into().unwrap(),
_ => {
panic!("Invalid value {}", N)
}
}
}
盡管代碼看起來像是在運行時檢查陣列大小,但 Godbolt表明 rustc/LLVM 能夠推斷出[f64; N].as_slice().try_into()總是成功地將陣列轉換為[f64; N]. 生成的代碼test<1>,test<2>因此不包含任何檢查或恐慌,并且只是由于萬能匹配臂中test<N>的N>2恐慌而無條件地恐慌。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/426689.html
上一篇:如何使函式回傳結構的泛型?
