2015-09-25 18 views
5

Lassen Sie uns sagen, ich habe eine Struktur Foo und ich möchte feststellen, ob Foo eine int innerhalb davon hat.Ermitteln, ob Struktur hat ein Mitglied von bestimmten Typ

struct Foo { int a; char c; }; 
has_int<Foo>::value; // should be true 

Dies ist die einfachste Form von dem, was ich eigentlich wollen würde, für einen bestimmten Typ Überprüfung:

has_type<Foo, int>::value; 

Wenn ich wüsste, wie die oben genannten tun ich es, was mein Ende verwandeln könnte Ziel ist:

has_pointer<Foo>::value; // false 
struct Bar { int a; void *b; }; 
has_pointer<Bar>::value; // true 

Als für das, was ich versucht habe, ist es schwer, um loszulegen, das beste, was ich von ist der Meinung, dass, wenn ich eine Packung der in einer Struktur enthalten Typen konnte ich das schreiben konnte Rest:

template <typename... Ts> 
constexpr bool any_is_pointer() noexcept { 
    return (... || std::is_pointer_v<Ts>); 
} 

Nach was ich frage scheint scheint es sehr wahrscheinlich unmöglich. Ich konnte kein Duplikat finden, aber ich war überrascht, dass ich es nicht könnte, also könnte es da draußen sein.

+0

Dies ist unmöglich, C++ hat keine Reflexion. Es ist jedoch sehr einfach für etwas wie ein 'std :: tuple'. – Barry

+0

Grundsätzlich wollen Sie Reflexion. C++ macht keine Reflektion. Aber ich kann mir nicht helfen, aber frage mich: Angenommen, du hast es irgendwie geschafft, 'has_int' zu implementieren - wie willst du es verwenden? Was ist das eigentliche Problem, das Sie versuchen zu lösen? –

+0

@IgorTandetnik Ich bin in einer Situation, in der Strukturen, die Zeiger oder Referenzen enthalten, feinfühlig behandelt werden müssen. Der Punkt wäre, zu entscheiden, welche Operationen zur Kompilierzeit erlaubt sind. Ich kann es nicht wirklich in einem Detail erklären. –

Antwort

1

Wie andere gesagt haben, was Sie wollen, ist jetzt unmöglich mit Vanille C++ für beliebige Typen. Wenn Sie jedoch neben den Typen, die Sie in ihrer Definition verwenden müssen, auch Informationen zur Kompilierungszeit bereitstellen können, können Sie das tun, was Sie tun möchten.

Sie können dies mit den Adaptern der Boost-Fusion-Bibliothek tun, mit denen Sie vorhandene Strukturen zu Fusionscontainern anpassen oder neue Strukturen definieren können, die einen Fusionscontainer modellieren. Sie können dann alle boost :: mpl-Algorithmen verwenden, mit denen Sie die gewünschten Kompilierungszeitprüfungen durchführen möchten.

dieses Beispiel Betrachten Sie Ihre struct foo verwenden und die has_type Kompilierung Algorithmus gewünscht:

#include <boost/fusion/adapted/struct/define_struct.hpp> 
#include <boost/mpl/contains.hpp> 

BOOST_FUSION_DEFINE_STRUCT(
    (your_namespace), foo, 
    (int, a) 
    (char, c)) 

template<typename source_type, typename search_type> 
struct has_type 
{ 
    typedef typename boost::mpl::contains<source_type, search_type>::type value_type; 
    static const bool value = value_type::value; 
}; 

#include <iostream> 

int main() 
{ 
    bool foo_has_int_pointer = has_type<your_namespace::foo, int*>::value; 
    bool foo_has_int = has_type<your_namespace::foo, int>::value; 

    std::cout << "foo_has_int_pointer: " << foo_has_int_pointer << "\n"; 
    std::cout << "foo_has_int: " << foo_has_int << "\n"; 

    your_namespace::foo my_foo; 

    my_foo.a = 10; 
    my_foo.c = 'x'; 

    std::cout << "my_foo: " << my_foo.a << ", " << my_foo.c; 
} 

Ansicht der Ausgang oder Durcheinander mit dem Beispiel hier: http://ideone.com/f0Zc2M

Wie Sie sehen können, verwenden Sie die BOOST_FUSION_DEFINE_STRUCT Makro, um die struct zu definieren, deren Mitglieder zur Kompilierungszeit ausgeführt werden sollen. Die Fusion bietet mehrere andere Makros zur Definition solcher Strukturen sowie Makros zur Anpassung bereits definierter Strukturen. Überprüfen Sie sie here.

Natürlich können Sie die Downside hier natürlich schon erkennen. has_type funktioniert nur, wenn source_type eine boost :: mpl/boost :: fusion sequenz ist. Für Sie bedeutet dies, dass jeder Typ, den Sie zur Kompilierzeit auf diese Weise ansprechen wollen, Sie mit den Makros definieren oder anpassen müssen. Dies ist möglicherweise für Sie nicht akzeptabel, wenn Sie eine Bibliothek schreiben, die für beliebige benutzerdefinierbare Bibliothekstypen geeignet ist.