2015-09-24 3 views

ответ

5

Во-первых, решите проблему без макросов. Одним из решений является создание недокументированные частных функций, которые не смогут компиляции, если ваши условия не выполняются:

struct MyType { 
    age: i32, 
    name: String, 
} 

fn __assert_send() 
where 
    MyType: Send, 
{} 

fn __assert_sync() 
where 
    MyType: Sync, 
{} 

// RFC 2056 
fn __assert_traits() { 
    __assert_send(); 
    __assert_sync(); 
} 

Затем изменить простое решение использовать макросы:

macro_rules! a { 
    ($n:ident, $t:ty) => { 
     struct $n { 
      x: $t 
     } 

     impl $n { 
      fn __assert_add() 
      where 
       $t: std::ops::Add<$t, Output = $t> 
      {} 

      fn __assert_mul() 
      where 
       $t: std::ops::Mul<$t, Output = $t> 
      {} 

      // RFC 2056 
      fn __assert_traits() { 
       Self::__assert_add(); 
       Self::__assert_mul(); 
      } 
     } 
    } 
} 

a!(Moo, u8); 
a!(Woof, bool); 

fn main() {} 

Я бы тогда верить в оптимизатор для удаления кода во время компиляции, поэтому я не ожидал бы дополнительного раздувания.

Главное спасибо до Chris Morgan за предоставление лучшей версии этого, которая поддерживает небезопасные свойства.

Стоит выделить RFC 2056, что позволит использовать «тривиальные» ограничения в тех случаях, когда предложения. После реализации положения, как это будет принято:

impl Foo for Bar 
where 
    i32: Iterator, 
{} 

Это точное поведение изменилось несколько раз в течение истории Русте и RFC 2056 штырей его вниз. Чтобы сохранить нужное поведение в этом случае, нам нужно вызвать функции утверждения из другой функции, которая не имеет ограничений (и, следовательно, всегда должна быть истина).

+3

Я отправился на 'fn _assert_add(), где Self: Добавить {} fn _verify_assertions() {Self :: _ assert_add()}', сам. Чуть более чистые сообщения об ошибках, на мой взгляд, и (что более важно) более общие, поскольку это не требует, чтобы этот признак был объектно-безопасным. –

+0

@ChrisMorgan не будет 'Self' быть созданным типом, а не типом поля? – Shepmaster

+2

О да, я не читал все это полностью. Но это не проблема - 'где $ t: Добавить <$ t, Output = $ t>' работает так же хорошо. Предложение 'where' может содержать материал для * любого * типа, а не только материал, связанный с' Self' или generics. –

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