2017-02-06 4 views
4

В C++ 11 вы можете разложить общий тип на тип значения, удалив семантику ссылки/rvalue и cv-квалификаторы, например.Распад типа C + 11-типа в ржавчине

decay<int>::type // type is `int` 
decay<const int&>::type // type is `int` 
decay<int&&>::type // type is `int` 

Есть ли известный механизм, чтобы достичь того же в Русте, что полоски опорных модификаторов, сроки службы и mut спецификатора? например .:

decay<u32>::type <--- type is `u32` 
decay<&u32>::type <--- type is `u32` 
decay<&mut u32>::type <--- type is `u32` 
decay<&static u32>::type <--- type is `u32` 

Для фона, я пытаюсь написать макрос, который генерирует struct, который хранит значения кучи аргументов функции совпавших с помощью макроса. например, макрос может содержать арг foo: i32, bar: &Vec<String>, и результирующая структура должна быть:

struct GeneratedStruct { 
    foo: i32, 
    bar: Vec<String>, 
} 
+1

Я думаю, что в Rust это будет обрабатываться непосредственно макросом, а не использовать черты (хотя вы можете сами создать свой признак). Помните, что макросы Rust работают в абстрактном дереве синтаксиса, а не в тексте, поэтому вы можете * анализировать * свои аргументы в макросе. –

+0

Deref может превратить & T в T, но если я не ошибаюсь, нет никакого способа узнать, что T не является самим собой. –

+0

@ MatthieuM. Я не думаю, что макрос может помочь, например. 'type I32Ref = & 'static i32; ...; decay! (I32Ref) 'должен создавать' i32', но на лексическом уровне это не известно. – kennytm

ответ

5

Как было предложено Matthieu M. и kennytm в комментариях, вы можете определить черта и использовать специализацию (нестабильная особенность, как Руст 1.15. 0) для достижения этого.

#![feature(specialization)] 

use std::any::TypeId; 

trait Decay { 
    type Type; 
} 

impl<T> Decay for T { 
    default type Type = T; 
} 

impl<'a, T> Decay for &'a T { 
    type Type = <T as Decay>::Type; 
} 

impl<'a, T> Decay for &'a mut T { 
    type Type = <T as Decay>::Type; 
} 

fn foo<T: 'static>() { 
    println!("{:?}", TypeId::of::<T>()); 
} 

fn bar<T>() where <T as Decay>::Type: 'static { 
    println!("{:?}", TypeId::of::<<T as Decay>::Type>()); 
} 

fn main() { 
    foo::<<i32 as Decay>::Type>(); 
    foo::<<&i32 as Decay>::Type>(); 
    foo::<<&mut i32 as Decay>::Type>(); 
    foo::<<&&i32 as Decay>::Type>(); 

    bar::<i32>(); 
    bar::<&i32>(); 
    bar::<&mut i32>(); 
    bar::<&&i32>(); 
} 
+0

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

+0

Ницца! Это делает работу. Я бы предпочел не сделать мою библиотеку неустойчивой - только. Я собираюсь продолжить изучение этого вопроса и посмотреть, смогу ли я придумать способ сделать это, используя стабильные функции. –

Смежные вопросы