2017-06-01 2 views
2

Ich versuche std::intrinsics::type_name zu verwenden, um den Typnamen eines Merkmals zu bekommen, aber es nicht kompilieren können:Gibt es eine Möglichkeit, den Typ eines Merkmals zu erhalten?

#![feature(core_intrinsics)] 

use std::intrinsics::type_name; 

trait TestTrait: Sized { 
    fn test(&self); 
} 

struct MyStruct {} 

struct GetType {} 

impl GetType { 
    fn test_type<T: ?Sized>() { 
     let test = unsafe { type_name::<T>() }; 
     println!("{:?}", test); 
    } 
} 

fn main() { 
    GetType::test_type::<i32>(); 
    GetType::test_type::<MyStruct>(); 
    GetType::test_type::<TestTrait>(); 
} 

Hier ist der Fehler, den ich aus dem Compiler

error[E0038]: the trait `TestTrait` cannot be made into an object 
    --> src/main.rs:23:30 
    | 
23 |   GetType::test_type::<TestTrait>(); 
    |        ^^^^^^^^^ the trait `TestTrait` cannot be made into an object 
    | 
    = note: the trait cannot require that `Self : Sized` 

Hier die erhalten ist Ausgang dieser Prüfung, wenn ich kommentieren Sie die Zeile GetType::test_type::<TestTrait>();

"i32" 
"MyStruct" 

gibt es eine Möglichkeit, dies zu lösen oder die Typenbezeichnung eines Merkmals zu bekommen?


Arbeitslösung dank

#![feature(core_intrinsics)] 

use std::intrinsics::type_name; 

trait TestTrait { // <--- remove `: Sized` constraint from here 
    fn test(&self); 
} 

struct MyStruct {} 

struct GetType {} 

impl GetType { 
    fn test_type<T: ?Sized>() { // <--- trick is in that bound 
     let test = unsafe { type_name::<T>() }; 
     println!("{:?}", test); 
    } 
} 

fn main() { 
    GetType::test_type::<i32>(); 
    GetType::test_type::<MyStruct>(); 
    GetType::test_type::<TestTrait>(); 
} 

Führende der folgenden Ausgabe

"i32" 
"MyStruct" 
"TestTrait" 

Antwort

3

Dies ist eigentlich explained in the docs ziemlich gut @evotopid:

Im Allgemeinen wird Self : Sized verwendet um anzuzeigen, dass das Merkmal nicht als Merkmalsobjekt verwendet werden soll. Wenn das Merkmal von Ihrer eigenen Kiste stammt, sollten Sie diese Einschränkung entfernen.

Wenn Sie Merkmal Objekte verwenden möchten, die ich dir raten wollen, denn sonst wäre es nicht sinnvoll, den Namen eines Merkmals zu erhalten, müssen Sie die Sized Einschränkung von Ihrer Eigenschaft Definition entfernen.

Sind Sie sicher, dass Sie intrinsische Substanzen benötigen? Höchstwahrscheinlich gibt es einen besseren Weg, der es Ihnen auch ermöglichen würde, in Zukunft stabile Rust zu verwenden.

+0

Danke für Ihre Antwort @evotopid. Wenn ich die Beschränkung "Sized" entferne, kann ich 'GetType :: test_type :: ();' nicht kompilieren (siehe meinen aktualisierten Post für die Kompilierungsfehlermeldung). Die einzige Möglichkeit, das zu umgehen, ist 'GetType :: test_type :: >();' das ist ziemlich umständlich (ich könnte noch die Zeichenfolge analysieren, um zu bekommen, was ich will, aber der Anruf ist etwas seltsam) Ich möchte den Namen des Merkmals als String erhalten, um dann in einer Karte verwendet zu werden, nicht als Merkmalsobjekt. Ich habe die Warnung über intrinsics gelesen, konnte aber keinen anderen Weg finden, das zu bekommen – Boris

+0

Das scheint zu funktionieren? https://play.rust-lang.org/?gist=8b8220dc22bfb9ffc070ac9c6748d38e&version=nightly&backtrace=0 – evotopid

+0

In der Tat musste ich eine ' 'Einschränkung auf die' test_type() 'Funktion hinzufügen. Toller Fang, danke (Bearbeitung meiner ursprünglichen Frage für Leser) – Boris

Verwandte Themen