一種方式來實現你想要的是以下幾點:
macro_rules! unique_args {
($($idents:ident),*) => {
{
#[allow(dead_code, non_camel_case_types)]
enum Idents { $($idents,)* __CountIdentsLast }
}
};
}
macro_rules! _my_elem {
($val:expr, $($var:expr),*) => {{
$($val == $var)||*
}};
}
macro_rules! my_elem {
($($tt:tt)*) => {{
unique_args!($($tt)*);
_my_elem!($($tt)*)
}};
}
的想法是,具有兩倍相同標識符會導致一個編譯器錯誤,因爲枚舉不能有重複的異名。
您可以使用此爲這樣:
if my_elem!(w, x, y, z) {
println!("{}", w);
}
這是一個錯誤的例子:
// error[E0428]: a value named `y` has already been defined in this enum
if my_elem!(w, x, y, y) {
println!("{}", w);
}
然而,這隻會使用標識符的工作。
如果你想用文字,以及,你需要用不同的語法宏成能夠在文字和標識來區分:
macro_rules! unique_idents {
() => {
};
($tt:tt) => {
};
($ident1:ident, $ident2:ident) => {
{
#[allow(dead_code, non_camel_case_types)]
enum Idents {
$ident1,
$ident2,
}
}
};
($ident:ident, lit $expr:expr) => {
};
($ident1:ident, $ident2:ident, $($tt:tt)*) => {
{
#[allow(dead_code, non_camel_case_types)]
enum Idents {
$ident1,
$ident2,
}
unique_idents!($ident1, $($tt)*);
unique_idents!($ident2, $($tt)*);
}
};
($ident:ident, lit $expr:expr, $($tt:tt)*) => {
unique_idents!($ident, $($tt)*);
};
(lit $expr:expr, $($tt:tt)*) => {
unique_idents!($($tt)*);
};
}
macro_rules! unique_literals {
() => {
};
($tt:tt) => {
};
(lit $lit1:expr, lit $lit2:expr) => {{
type ArrayForStaticAssert_ = [i8; 0 - (($lit1 == $lit2) as usize)];
}};
(lit $lit:expr, $ident:ident) => {
};
(lit $lit1:expr, lit $lit2:ident, $($tt:tt)*) => {{
unique_literals!(lit $lit1, lit $lit2);
unique_literals!(lit $lit1, $($tt)*);
unique_literals!(lit $lit2, $($tt)*);
}};
(lit $lit:expr, $ident:ident, $($tt:tt)*) => {
unique_literals!(lit $lit, $($tt)*);
};
($ident:ident, $($tt:tt)*) => {
unique_literals!($($tt)*);
};
}
macro_rules! unique_args2 {
($($tt:tt)*) => {{
unique_idents!($($tt)*);
unique_literals!($($tt)*);
}};
}
macro_rules! _elem {
() => {
false
};
($val:expr) => {
false
};
($val1:expr, $val2:expr) => {{
$val1 == $val2
}};
($val1:expr, lit $val2:expr) => {{
$val1 == $val2
}};
($val1:expr, $val2:expr, $($tt:tt)*) => {{
$val1 == $val2 || _elem!($val1, $($tt)*)
}};
($val1:expr, lit $val2:expr, $($tt:tt)*) => {{
$val1 == $val2 || _elem!($val1, $($tt)*)
}};
}
macro_rules! elem {
($($tt:tt)*) => {{
unique_args2!($($tt)*);
_elem!($($tt)*)
}};
}
的uniq_idents!
宏使用同樣的伎倆如上。
宏unique_literals!
將導致subtract with overflow
在編譯時捕獲的錯誤。
有了這些宏,則需要通過3210前綴每個文字:
if elem!(w, x, lit 1, z) {
println!("{}", w);
}
下面是錯誤的一些例子:
// error[E0428]: a value named `y` has already been defined in this enum
if elem!(w, x, y, y) {
println!("{}", w);
}
// error[E0080]: constant evaluation error
if elem!(w, x, lit 1, z, lit 1) {
println!("{}", w);
}
我認爲這是我們不使用能做的最好的一個編譯器插件。
可以改進這些宏,但你明白了。
儘管有一個stringify!
宏可用於將任何表達式轉換爲字符串,但我認爲我們現在沒有辦法在編譯時比較這些字符串(沒有編譯器插件),至少直到我們有const fn
。
如果我的回答不是你要找的,你能否發表評論來解釋爲什麼? – antoyo