是否可以访问用于函数签名或声明的结构成员的类型?
在宏中定义实现时,访问结构成员类型以避免将其作为额外参数传递可能很有用.(参见这个问题)
When defining implementations in macros, it might be useful to access a struct members type to avoid having to pass it as an extra argument. (see this question)
impl PartialEq<u32> for MyStruct { ... }
有没有办法在不事先知道它是哪种类型的情况下访问结构成员的类型?
Is there a way to access the type of a struct member without knowing in advance which type it is?
impl PartialEq<typeof(MyStruct.member)> for MyStruct { ... }
如果有帮助,以下是我感兴趣的原因的简短示例:
In case it's helpful, this is an abbreviated example of why I'm interested to do this:
struct_bitflag_impl!(
pub struct MyFlag(u8);,
MyFlag, u8);
// ^^ how to avoid having this extra arg?
// (Used by ``impl PartialEq<$t_internal> for $p``)
// couldn't it be discovered from `MyFlag.0` ?
// the macro
macro_rules! struct_bitflag_impl {
($struct_p_def: item, $p:ident, $t_internal:ty) => {
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
$struct_p_def
impl ::std::ops::BitAnd for $p {
type Output = $p;
fn bitand(self, _rhs: $p) -> $p { $p(self.0 & _rhs.0) }
}
impl ::std::ops::BitOr for $p {
type Output = $p;
fn bitor(self, _rhs: $p) -> $p { $p(self.0 | _rhs.0) }
}
impl ::std::ops::BitXor for $p {
type Output = $p;
fn bitxor(self, _rhs: $p) -> $p { $p(self.0 ^ _rhs.0) }
}
impl ::std::ops::Not for $p {
type Output = $p;
fn not(self) -> $p { $p(!self.0) }
}
// support comparison with the base-type.
impl PartialEq<$t_internal> for $p {
fn eq(&self, other: &t_internal) -> bool {
self.0 == *other
}
}
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// How to avoid using 't_internal' here?
}
}
不,一般的typeof(Type::field)
可用于类型位置的不存在.
No, a general typeof(Type::field)
that can be used in type position does not exist.
关于问题中的示例,您似乎在期待一种特殊的项目:只有一个字段的元组结构.因此,您可以自己模拟语法,而不是接受 $item
片段:
Regarding the example in the question, it looks like you are expecting a special kind of item: a tuple-struct with only one field. So, instead of accepting an $item
fragment, you can simulate the syntax yourself:
macro_rules! foo {
(pub struct $name:ident ( $ty:ident ) ) => {
pub struct $name($ty);
impl $name {
pub fn bar() {
println!("{}", stringify!($ty));
}
}
}
}
foo!(
pub struct Peter(u8)
);
fn main() {
Peter::bar();
}
这样你只需指定一次.然而,这显然只适用于一种元组结构定义,而不是所有类型的项目.但是您的用例表明您或多或少只对这种特殊情况感兴趣.
That way you only have to specify everything once. However, this obviously only works with one kind of tuple-struct definition, not all kinds of items. But your use case suggests that you are more or less only interested in this special case.
如果你想允许不同类型的结构定义,你只需要在宏中添加更多的宏规则以允许不同的语法.要查看示例,这里是允许 pub
和非pub
元组结构定义.但这可以进一步扩展.
If you want to allow different kinds of struct definitions, you just need to add more macro-rules to the macro to allow for different syntax. To see an example, here is code to allow for pub
and non-pub
tuple-struct definitions. But this could be expanded even more.