Check für is member function pointer
-
Nash26 schrieb:
@wxSkip
das heißt also ich kann direkttemplate <typename T, typename C> struct is_mem_fun_ptr<T C::*> : true_type {};schreiben?
Nein. Es gibt auch Nicht-Memberfunktions-Typen, die auf diese Spezialisierung passen. Und zwar sind das die relativ unbekannten Zeiger auf Member. Wenn du eine Klasse mit verschiedenen Variablen hast, kannst du einen Zeiger auf eine Klassenvariable holen, der praktisch die interne Position in der Klasse speichert. Wenn du dann noch ein konkretes Objekt hast, kannst du mit diesem Zeiger auf die Variable dieses Objektes zugreifen.
-
Nash26 schrieb:
jetzt zu dem Konstrukt:
template <typename T> struct is_function : is_same<void(void(int,int)),void(void(*)(int,int))> {};Auf der linken Seite deklarierst du einen Funktionszeiger, dieser wird durch den compiler nochmal
zu einem Funktionszeiger transformiert? Auf der rechten Seite machen wir das manuell. Ist das so korrekt?Links wird ein Funktionstyp deklariert, rechts wird ein Funktionstyp deklariert. Beiden Typen haben ihrerseits einen Funktionszeiger als Parametertyp.
Nash26 schrieb:
PS: wo lernt man solche Tricks mit
is_same<void(T),void(T*)> {};
?
Also das wäre mit nicht im traum eingefallen.Den Trick als solchen habe ich mir on-the-fly beim Schreiben ausgedacht. Den zugrunde liegenden Mechanismus lernt man irgendwann nebenbei kennen, wenn es um etwas ganz anderes geht.
-
@camper
tja bleibt nur noch die Frage warum es mit VS2008 nicht mit const methoden klappt.
Hast du einen workaround dafür?
-
ich bekomme es einfach nicht hin:
template <typename T, typename C> struct is_mem_fun_ptr<T const C::*> : is_function<T> {};wenn ich das template mit einer const member function aufrufe wird sofort:
template <typename T> struct is_mem_fun_ptr : false_type {};instanziiert
auch den const qualifier zu entfernen klappt nicht.
-
Nash26 schrieb:
@camper
tja bleibt nur noch die Frage warum es mit VS2008 nicht mit const methoden klappt.
Hast du einen workaround dafür?Nein. Es gilt dann einfach das, was ich zuerst gesagt habe.
Nash26 schrieb:
ich bekomme es einfach nicht hin:
template <typename T, typename C> struct is_mem_fun_ptr<T const C::*> : is_function<T> {};wenn ich das template mit einer const member function aufrufe wird sofort:
template <typename T> struct is_mem_fun_ptr : false_type {};instanziiert
auch den const qualifier zu entfernen klappt nicht.
Das ist kein Wunder.
Einen const/volatile-Qualifizierer zu einem Funktionstyp hinzuzufügen macht daraus gerade keinen const/volatile-Funktionstyp, je nach Kontext ist es schlicht illegal oder wird ignoriert.Die Spezialisierung
template <typename T, typename C> struct is_mem_fun_ptr<T const C::*> : is_function<T> {};würde folglich nur für Zeiger auf konstante Member (also vor allem keine Memberfunktionen) genutzt werden.
boost.type_traits hat bereits eine portable Lösung. Ich kann keine Bessere anbieten.
-
du hattest geschrieben
Das Testen auf non-const-non-volatile-Memberfunktionszeiger ist einfach. Schwierigkeiten machen nur const,volatile und const volatile-Memberfunktionen:
das heißt also, es gibt für VS2008 nur die Möglichkeit auf viele Spezialiserungen zu testen? Korrekt?
-
Nash26 schrieb:
du hattest geschrieben
Das Testen auf non-const-non-volatile-Memberfunktionszeiger ist einfach. Schwierigkeiten machen nur const,volatile und const volatile-Memberfunktionen:
das heißt also, es gibt für VS2008 nur die Möglichkeit auf viele Spezialiserungen zu testen? Korrekt?
Das, oder Ausschlussverfahren
#include <cstddef> template <bool b> struct bool_ { static const bool value = b; }; template <typename T> struct not_ { static const bool value = !T::value; }; typedef bool_<true> true_type; typedef bool_<false> false_type; template <typename T> struct identity { typedef T type; }; // is_same template <typename T, typename U> struct is_same : false_type {}; template <typename T> struct is_same<T, T> : true_type {}; // add_reference template <typename T> struct add_reference : identity<T&> {}; template <typename T> struct add_reference<T&> : identity<T&> {}; // remove_reference (funktioniert auch mit rvalue-Referenzen) template <typename T> struct remove_reference : remove_reference<typename add_reference<T>::type> {}; template <typename T> struct remove_reference<T&> : identity<T> {}; // is_reference (funktioniert auch mit rvalue-Referenzen) template <typename T> struct is_reference : not_<is_same<T, typename remove_reference<typename add_reference<T>::type>::type> > {}; // is_pointer template <typename T> struct is_pointer : false_type {}; template <typename T> struct is_pointer<T*> : true_type {}; // is_class (class/struct/union) template <typename T> struct is_class { typedef char& yes_type; typedef char (&no_type)[2]; template <typename U> static no_type test(...); template <typename U> static yes_type test(int U::*); static const bool value = sizeof test<T>(0) == sizeof(yes_type); }; // is_array template <typename T> struct is_array : false_type {}; template <typename T> struct is_array<T[]> : true_type {}; template <typename T, std::size_t N> struct is_array<T[N]> : true_type {}; // is_void template <typename T> struct is_void : false_type {}; template <> struct is_void<void> : true_type {}; template <> struct is_void<const void> : true_type {}; template <> struct is_void<volatile void> : true_type {}; template <> struct is_void<const volatile void> : true_type {}; // is_function template <typename T, bool = !is_void<T>::value && !is_reference<T>::value> struct is_function : is_same<void(T),void(T*)> {}; template <typename T> struct is_function<T, false> : false_type {}; // is_convertible template <typename T, typename U> struct is_convertible { static typename add_reference<T>::type makeT(); typedef char& yes_type; typedef char (&no_type)[2]; static no_type test(...); static yes_type test(U); static const bool value = sizeof test(makeT()) == sizeof(yes_type); }; // is_convertible_static template <typename T, typename U> struct is_convertible_static { static typename add_reference<T>::type makeT(); typedef char& yes_type; typedef char (&no_type)[2]; template <typename V> static no_type test(...); template <typename V> static yes_type test(char(*)[sizeof(static_cast<V>(makeT()))]); static const bool value = sizeof test<U>(0) == sizeof(yes_type); }; // is_fundamental_or_enum (including scoped enums) template <typename T> struct is_fundamental_or_enum : bool_<is_void<T>::value || ( !is_class<T>::value && !is_reference<T>::value && is_convertible_static<T, int>::value )> {}; // is_mem_data_ptr template <typename T> struct is_mem_data_ptr : false_type {}; template <typename T, typename C> struct is_mem_data_ptr<T C::*> : not_<is_function<T> > {}; // is_mem_fun_ptr template <typename T> struct is_mem_fun_ptr : bool_<!is_fundamental_or_enum<T>::value && !is_class<T>::value && !is_pointer<T>::value && !is_reference<T>::value && !is_function<T>::value && !is_array<T>::value && !is_mem_data_ptr<T>::value> {}; #include <iostream> enum A { a, b, c }; enum class B { d, e, f }; struct C {}; union D {}; int main() { using std::cout; cout << "\t\t\tint\tint&\tint&&\tint[6]\tint*\tint()\tint(*)();int(&)();enum A;ec B\tstructC\tunionD\tint D::*;int(D::*)();int(D::*)const\n"; cout << "is_reference\t" << '\t'; cout << is_reference<int>::value << '\t'; cout << is_reference<int&>::value << '\t'; cout << is_reference<int&&>::value << '\t'; cout << is_reference<int[6]>::value << '\t'; cout << is_reference<int*>::value << '\t'; cout << is_reference<int()>::value << '\t'; cout << is_reference<int(*)()>::value << '\t'; cout << is_reference<int(&)()>::value << '\t'; cout << is_reference<A>::value << '\t'; cout << is_reference<B>::value << '\t'; cout << is_reference<C>::value << '\t'; cout << is_reference<D>::value << '\t'; cout << is_reference<int D::*>::value << '\t'; cout << is_reference<int (D::*)()>::value << '\t'; cout << is_reference<int (D::*)()const>::value << '\n'; cout << "is_array\t" << '\t'; cout << is_array<int>::value << '\t'; cout << is_array<int&>::value << '\t'; cout << is_array<int&&>::value << '\t'; cout << is_array<int[6]>::value << '\t'; cout << is_array<int*>::value << '\t'; cout << is_array<int()>::value << '\t'; cout << is_array<int(*)()>::value << '\t'; cout << is_array<int(&)()>::value << '\t'; cout << is_array<A>::value << '\t'; cout << is_array<B>::value << '\t'; cout << is_array<C>::value << '\t'; cout << is_array<D>::value << '\t'; cout << is_array<int D::*>::value << '\t'; cout << is_array<int (D::*)()>::value << '\t'; cout << is_array<int (D::*)()const>::value << '\n'; cout << "is_pointer\t" << '\t'; cout << is_pointer<int>::value << '\t'; cout << is_pointer<int&>::value << '\t'; cout << is_pointer<int&&>::value << '\t'; cout << is_pointer<int[6]>::value << '\t'; cout << is_pointer<int*>::value << '\t'; cout << is_pointer<int()>::value << '\t'; cout << is_pointer<int(*)()>::value << '\t'; cout << is_pointer<int(&)()>::value << '\t'; cout << is_pointer<A>::value << '\t'; cout << is_pointer<B>::value << '\t'; cout << is_pointer<C>::value << '\t'; cout << is_pointer<D>::value << '\t'; cout << is_pointer<int D::*>::value << '\t'; cout << is_pointer<int (D::*)()>::value << '\t'; cout << is_pointer<int (D::*)()const>::value << '\n'; cout << "is_function\t" << '\t'; cout << is_function<int>::value << '\t'; cout << is_function<int&>::value << '\t'; cout << is_function<int&&>::value << '\t'; cout << is_function<int[6]>::value << '\t'; cout << is_function<int*>::value << '\t'; cout << is_function<int()>::value << '\t'; cout << is_function<int(*)()>::value << '\t'; cout << is_function<int(&)()>::value << '\t'; cout << is_function<A>::value << '\t'; cout << is_function<B>::value << '\t'; cout << is_function<C>::value << '\t'; cout << is_function<D>::value << '\t'; cout << is_function<int D::*>::value << '\t'; cout << is_function<int (D::*)()>::value << '\t'; cout << is_function<int (D::*)()const>::value << '\n'; cout << "is_class\t" << '\t'; cout << is_class<int>::value << '\t'; cout << is_class<int&>::value << '\t'; cout << is_class<int&&>::value << '\t'; cout << is_class<int[6]>::value << '\t'; cout << is_class<int*>::value << '\t'; cout << is_class<int()>::value << '\t'; cout << is_class<int(*)()>::value << '\t'; cout << is_class<int(&)()>::value << '\t'; cout << is_class<A>::value << '\t'; cout << is_class<B>::value << '\t'; cout << is_class<C>::value << '\t'; cout << is_class<D>::value << '\t'; cout << is_class<int D::*>::value << '\t'; cout << is_class<int (D::*)()>::value << '\t'; cout << is_class<int (D::*)()const>::value << '\n'; cout << "is_fund_or_enum\t" << '\t'; cout << is_fundamental_or_enum<int>::value << '\t'; cout << is_fundamental_or_enum<int&>::value << '\t'; cout << is_fundamental_or_enum<int&&>::value << '\t'; cout << is_fundamental_or_enum<int[6]>::value << '\t'; cout << is_fundamental_or_enum<int*>::value << '\t'; cout << is_fundamental_or_enum<int()>::value << '\t'; cout << is_fundamental_or_enum<int(*)()>::value << '\t'; cout << is_fundamental_or_enum<int(&)()>::value << '\t'; cout << is_fundamental_or_enum<A>::value << '\t'; cout << is_fundamental_or_enum<B>::value << '\t'; cout << is_fundamental_or_enum<C>::value << '\t'; cout << is_fundamental_or_enum<D>::value << '\t'; cout << is_fundamental_or_enum<int D::*>::value << '\t'; cout << is_fundamental_or_enum<int (D::*)()>::value << '\t'; cout << is_fundamental_or_enum<int (D::*)()const>::value << '\n'; cout << "is_mem_data_ptr\t" << '\t'; cout << is_mem_data_ptr<int>::value << '\t'; cout << is_mem_data_ptr<int&>::value << '\t'; cout << is_mem_data_ptr<int&&>::value << '\t'; cout << is_mem_data_ptr<int[6]>::value << '\t'; cout << is_mem_data_ptr<int*>::value << '\t'; cout << is_mem_data_ptr<int()>::value << '\t'; cout << is_mem_data_ptr<int(*)()>::value << '\t'; cout << is_mem_data_ptr<int(&)()>::value << '\t'; cout << is_mem_data_ptr<A>::value << '\t'; cout << is_mem_data_ptr<B>::value << '\t'; cout << is_mem_data_ptr<C>::value << '\t'; cout << is_mem_data_ptr<D>::value << '\t'; cout << is_mem_data_ptr<int D::*>::value << '\t'; cout << is_mem_data_ptr<int (D::*)()>::value << '\t'; cout << is_mem_data_ptr<int (D::*)()const>::value << '\n'; cout << "is_mem_fun_ptr\t" << '\t'; cout << is_mem_fun_ptr<int>::value << '\t'; cout << is_mem_fun_ptr<int&>::value << '\t'; cout << is_mem_fun_ptr<int&&>::value << '\t'; cout << is_mem_fun_ptr<int[6]>::value << '\t'; cout << is_mem_fun_ptr<int*>::value << '\t'; cout << is_mem_fun_ptr<int()>::value << '\t'; cout << is_mem_fun_ptr<int(*)()>::value << '\t'; cout << is_mem_fun_ptr<int(&)()>::value << '\t'; cout << is_mem_fun_ptr<A>::value << '\t'; cout << is_mem_fun_ptr<B>::value << '\t'; cout << is_mem_fun_ptr<C>::value << '\t'; cout << is_mem_fun_ptr<D>::value << '\t'; cout << is_mem_fun_ptr<int D::*>::value << '\t'; cout << is_mem_fun_ptr<int (D::*)()>::value << '\t'; cout << is_mem_fun_ptr<int (D::*)()const>::value << '\n'; }sollte funktionieren (rvalue-Rereferenzen bei alten Compilern weglassen).
-
Nochmal ein bisschen überarbeitet. Diese Version funktioniert mindestens ab gcc 3.4, Comeau-C++ und clang 3.1 sind auch zufrieden.
rvalue-Referenzen und scoped enums werden unterstützt, es werden aber keine C++11-Features verwendet. Es sollte auch mit extended integer Typen funktionieren, allerdings kann ich das nicht testen.
Was sagt Visual C++ dazu?#include <cstddef> template <bool b> struct bool_ { static const bool value = b; }; template <typename T> struct not_ { static const bool value = !T::value; }; typedef bool_<true> true_type; typedef bool_<false> false_type; template <typename T> struct identity { typedef T type; }; template <typename T> struct is_void; template <typename T> struct is_array; template <typename T, bool = is_void<T>::value || is_array<T>::value> struct is_reference; template <typename T> struct is_class; // transformations template <typename T, bool = is_void<T>::value> struct add_reference : identity<T&> {}; template <typename T, bool b> struct add_reference<T&, b> : identity<T&> {}; template <typename T> struct add_reference<T, true> : identity<T> {}; template <typename T, bool = is_void<T>::value> struct remove_reference : remove_reference<typename add_reference<T>::type> {}; template <typename T, bool b> struct remove_reference<T&, b> : identity<T> {}; template <typename T> struct remove_reference<T, true> : identity<T> {}; template <typename T> struct remove_const : identity<T> {}; template <typename T> struct remove_const<const T> : identity<T> {}; template <typename T> struct remove_volatile : identity<T> {}; template <typename T> struct remove_volatile<volatile T> : identity<T> {}; template <typename T> struct remove_cv : remove_volatile<typename remove_const<T>::type> {}; // relations template <typename T, typename U> struct is_same : false_type {}; template <typename T> struct is_same<T, T> : true_type {}; template <typename T, typename U, bool = is_void<T>::value> struct is_convertible { static typename add_reference<T>::type makeT(); typedef char& yes_type; typedef char (&no_type)[2]; template <typename V> static no_type test(...); template <typename V> static yes_type test(V); static const bool value = sizeof test<U>(makeT()) == sizeof(yes_type); }; template <typename T, typename U> struct is_convertible<T[], U, false> : is_convertible<T*, U, false> {}; template <typename T, std::size_t N, typename U> struct is_convertible<T[N], U, false> : is_convertible<T*, U, false> {}; template <typename T, typename U> struct is_convertible<T, U, true> : is_void<U> {}; // predicates template <typename T> struct is_void : is_same<typename remove_cv<T>::type, void> {}; template <typename T> struct is_arithmetic : bool_<!is_class<T>::value && !is_reference<T>::value && is_convertible<T, int>::value && is_convertible<int, T>::value> {}; template <typename T> struct is_fundamental: bool_<is_arithmetic<T>::value || is_void<T>::value> {}; template <typename T> struct is_array : false_type {}; template <typename T> struct is_array<T[]> : true_type {}; template <typename T, std::size_t N> struct is_array<T[N]> : true_type {}; template <typename T, bool = !is_void<T>::value && !is_reference<T>::value && !is_array<T>::value> struct is_function : is_same<void(T),void(T*)> {}; template <typename T> struct is_function<T, false> : false_type {}; template <typename T> struct is_object : bool_<!is_void<T>::value && !is_reference<T>::value && !is_function<T>::value> {}; template <typename T> struct is_pointer : false_type {}; template <typename T> struct is_pointer<T*> : true_type {}; template <typename T, bool> struct is_reference : not_<is_same<T, typename remove_reference<typename add_reference<T>::type>::type> > {}; template <typename T> struct is_reference<T, true> : false_type {}; template <typename T> struct is_class { typedef char& yes_type; typedef char (&no_type)[2]; template <typename U> static no_type test(...); template <typename U> static yes_type test(int U::*); static const bool value = sizeof test<T>(0) == sizeof(yes_type); }; template <typename T> struct is_unscoped_enum : bool_<is_object<T>::value && !is_fundamental<T>::value && !is_class<T>::value && is_convertible<T, int>::value> {}; template <typename T, bool = is_object<T>::value && !is_class<T>::value && !is_fundamental<T>::value && !is_array<T>::value && !is_pointer<T>::value && !is_unscoped_enum<T>::value> struct is_scoped_enum : not_<is_convertible<T, bool> > {}; template <typename T> struct is_scoped_enum<T, false> : false_type {}; template <typename T> struct is_enum : bool_<is_unscoped_enum<T>::value || is_scoped_enum<T>::value> {}; template <typename T> struct is_mem_data_ptr : false_type {}; template <typename T, typename C> struct is_mem_data_ptr<T C::*> : is_object<typename remove_reference<T>::type> {}; template <typename T> struct is_mem_fun_ptr : bool_<is_object<T>::value && !is_class<T>::value && !is_fundamental<T>::value && !is_array<T>::value && !is_pointer<T>::value && !is_enum<T>::value && !is_mem_data_ptr<T>::value> {}; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// template <bool b> struct assertion_failure; template <> struct assertion_failure<true> : true_type {}; #define FUSE( x, y ) x##y #define STATIC_ASSERT( T, x, v ) typedef int FUSE( assert, __LINE__ ) [sizeof(assertion_failure<T<x>::value==v>::value)] typedef int arithmetic_type; typedef void void_type; typedef int& lref_type; typedef int array_type[42]; typedef int array_type2[]; typedef int***** pointer_type; typedef int fun_type(); typedef int(*pfun_type)(); typedef int(&fun_ref_type)(); enum enum_type {}; struct struct_type {}; union union_type {}; typedef enum_type (struct_type::*mem_data_ptr_type_helper)() const; typedef mem_data_ptr_type_helper struct_type::*mem_data_ptr_type; typedef enum_type (struct_type::*mem_fun_ptr_type_)(); typedef mem_data_ptr_type (struct_type::*mem_fun_ptr_type)() const; typedef mem_fun_ptr_type_ (struct_type::*mem_fun_ptr_type2)() const; #ifdef WITHCPP11 enum class enum_class_type {}; #define ENUM_CLASS_IS_SCOPED true typedef int&& rref_type; #else enum enum_class_type {}; #define ENUM_CLASS_IS_SCOPED false typedef int& rref_type; #endif int main() { STATIC_ASSERT( is_class, arithmetic_type, false ); STATIC_ASSERT( is_class, void_type, false ); STATIC_ASSERT( is_class, lref_type, false ); STATIC_ASSERT( is_class, rref_type, false ); STATIC_ASSERT( is_class, array_type, false ); STATIC_ASSERT( is_class, array_type2, false ); STATIC_ASSERT( is_class, pointer_type, false ); STATIC_ASSERT( is_class, fun_type, false ); STATIC_ASSERT( is_class, pfun_type, false ); STATIC_ASSERT( is_class, fun_ref_type, false ); STATIC_ASSERT( is_class, enum_type, false ); STATIC_ASSERT( is_class, enum_class_type, false ); STATIC_ASSERT( is_class, struct_type, true ); STATIC_ASSERT( is_class, union_type, true ); STATIC_ASSERT( is_class, mem_data_ptr_type, false ); STATIC_ASSERT( is_class, mem_fun_ptr_type, false ); STATIC_ASSERT( is_class, mem_fun_ptr_type2, false ); STATIC_ASSERT( is_arithmetic, arithmetic_type, true ); STATIC_ASSERT( is_arithmetic, void_type, false ); STATIC_ASSERT( is_arithmetic, lref_type, false ); STATIC_ASSERT( is_arithmetic, rref_type, false ); STATIC_ASSERT( is_arithmetic, array_type, false ); STATIC_ASSERT( is_arithmetic, array_type2, false ); STATIC_ASSERT( is_arithmetic, pointer_type, false ); STATIC_ASSERT( is_arithmetic, fun_type, false ); STATIC_ASSERT( is_arithmetic, pfun_type, false ); STATIC_ASSERT( is_arithmetic, fun_ref_type, false ); STATIC_ASSERT( is_arithmetic, enum_type, false ); STATIC_ASSERT( is_arithmetic, enum_class_type, false ); STATIC_ASSERT( is_arithmetic, struct_type, false); STATIC_ASSERT( is_arithmetic, union_type, false); STATIC_ASSERT( is_arithmetic, mem_data_ptr_type, false ); STATIC_ASSERT( is_arithmetic, mem_fun_ptr_type, false ); STATIC_ASSERT( is_arithmetic, mem_fun_ptr_type2, false ); STATIC_ASSERT( is_void, arithmetic_type, false ); STATIC_ASSERT( is_void, void_type, true ); STATIC_ASSERT( is_void, lref_type, false ); STATIC_ASSERT( is_void, rref_type, false ); STATIC_ASSERT( is_void, array_type, false ); STATIC_ASSERT( is_void, array_type2, false ); STATIC_ASSERT( is_void, pointer_type, false ); STATIC_ASSERT( is_void, fun_type, false ); STATIC_ASSERT( is_void, pfun_type, false ); STATIC_ASSERT( is_void, fun_ref_type, false ); STATIC_ASSERT( is_void, enum_type, false ); STATIC_ASSERT( is_void, enum_class_type, false ); STATIC_ASSERT( is_void, struct_type, false ); STATIC_ASSERT( is_void, union_type, false ); STATIC_ASSERT( is_void, mem_data_ptr_type, false ); STATIC_ASSERT( is_void, mem_fun_ptr_type, false ); STATIC_ASSERT( is_void, mem_fun_ptr_type2, false ); STATIC_ASSERT( is_fundamental, arithmetic_type, true ); STATIC_ASSERT( is_fundamental, void_type, true ); STATIC_ASSERT( is_fundamental, lref_type, false ); STATIC_ASSERT( is_fundamental, rref_type, false ); STATIC_ASSERT( is_fundamental, array_type, false ); STATIC_ASSERT( is_fundamental, array_type2, false ); STATIC_ASSERT( is_fundamental, pointer_type, false ); STATIC_ASSERT( is_fundamental, fun_type, false ); STATIC_ASSERT( is_fundamental, pfun_type, false ); STATIC_ASSERT( is_fundamental, fun_ref_type, false ); STATIC_ASSERT( is_fundamental, enum_type, false ); STATIC_ASSERT( is_fundamental, enum_class_type, false ); STATIC_ASSERT( is_fundamental, struct_type, false ); STATIC_ASSERT( is_fundamental, union_type, false ); STATIC_ASSERT( is_fundamental, mem_data_ptr_type, false ); STATIC_ASSERT( is_fundamental, mem_fun_ptr_type, false ); STATIC_ASSERT( is_fundamental, mem_fun_ptr_type2, false ); STATIC_ASSERT( is_array, arithmetic_type, false ); STATIC_ASSERT( is_array, void_type, false ); STATIC_ASSERT( is_array, lref_type, false ); STATIC_ASSERT( is_array, rref_type, false ); STATIC_ASSERT( is_array, array_type, true ); STATIC_ASSERT( is_array, array_type2, true ); STATIC_ASSERT( is_array, pointer_type, false ); STATIC_ASSERT( is_array, fun_type, false ); STATIC_ASSERT( is_array, pfun_type, false ); STATIC_ASSERT( is_array, fun_ref_type, false ); STATIC_ASSERT( is_array, enum_type, false ); STATIC_ASSERT( is_array, enum_class_type, false ); STATIC_ASSERT( is_array, struct_type, false ); STATIC_ASSERT( is_array, union_type, false ); STATIC_ASSERT( is_array, mem_data_ptr_type, false ); STATIC_ASSERT( is_array, mem_fun_ptr_type, false ); STATIC_ASSERT( is_array, mem_fun_ptr_type2, false ); STATIC_ASSERT( is_reference, arithmetic_type, false ); STATIC_ASSERT( is_reference, void_type, false ); STATIC_ASSERT( is_reference, lref_type, true ); STATIC_ASSERT( is_reference, rref_type, true ); STATIC_ASSERT( is_reference, array_type, false ); STATIC_ASSERT( is_reference, array_type2, false ); STATIC_ASSERT( is_reference, pointer_type, false ); STATIC_ASSERT( is_reference, fun_type, false ); STATIC_ASSERT( is_reference, pfun_type, false ); STATIC_ASSERT( is_reference, fun_ref_type, true ); STATIC_ASSERT( is_reference, enum_type, false ); STATIC_ASSERT( is_reference, enum_class_type, false ); STATIC_ASSERT( is_reference, struct_type, false ); STATIC_ASSERT( is_reference, union_type, false ); STATIC_ASSERT( is_reference, mem_data_ptr_type, false ); STATIC_ASSERT( is_reference, mem_fun_ptr_type, false ); STATIC_ASSERT( is_reference, mem_fun_ptr_type2, false ); STATIC_ASSERT( is_pointer, arithmetic_type, false ); STATIC_ASSERT( is_pointer, void_type, false ); STATIC_ASSERT( is_pointer, lref_type, false ); STATIC_ASSERT( is_pointer, rref_type, false ); STATIC_ASSERT( is_pointer, array_type, false ); STATIC_ASSERT( is_pointer, array_type2, false ); STATIC_ASSERT( is_pointer, pointer_type, true ); STATIC_ASSERT( is_pointer, fun_type, false ); STATIC_ASSERT( is_pointer, pfun_type, true ); STATIC_ASSERT( is_pointer, fun_ref_type, false ); STATIC_ASSERT( is_pointer, enum_type, false ); STATIC_ASSERT( is_pointer, enum_class_type, false ); STATIC_ASSERT( is_pointer, struct_type, false ); STATIC_ASSERT( is_pointer, union_type, false ); STATIC_ASSERT( is_pointer, mem_data_ptr_type, false ); STATIC_ASSERT( is_pointer, mem_fun_ptr_type, false ); STATIC_ASSERT( is_pointer, mem_fun_ptr_type2, false ); STATIC_ASSERT( is_object, arithmetic_type, true ); STATIC_ASSERT( is_object, void_type, false ); STATIC_ASSERT( is_object, lref_type, false ); STATIC_ASSERT( is_object, rref_type, false ); STATIC_ASSERT( is_object, array_type, true ); STATIC_ASSERT( is_object, array_type2, true ); STATIC_ASSERT( is_object, pointer_type, true ); STATIC_ASSERT( is_object, fun_type, false ); STATIC_ASSERT( is_object, pfun_type, true ); STATIC_ASSERT( is_object, fun_ref_type, false ); STATIC_ASSERT( is_object, enum_type, true ); STATIC_ASSERT( is_object, enum_class_type, true ); STATIC_ASSERT( is_object, struct_type, true ); STATIC_ASSERT( is_object, union_type, true ); STATIC_ASSERT( is_object, mem_data_ptr_type, true ); STATIC_ASSERT( is_object, mem_fun_ptr_type, true ); STATIC_ASSERT( is_object, mem_fun_ptr_type2, true ); STATIC_ASSERT( is_function, arithmetic_type, false ); STATIC_ASSERT( is_function, void_type, false ); STATIC_ASSERT( is_function, lref_type, false ); STATIC_ASSERT( is_function, rref_type, false ); STATIC_ASSERT( is_function, array_type, false ); STATIC_ASSERT( is_function, array_type2, false ); STATIC_ASSERT( is_function, pointer_type, false ); STATIC_ASSERT( is_function, fun_type, true ); STATIC_ASSERT( is_function, pfun_type, false ); STATIC_ASSERT( is_function, fun_ref_type, false ); STATIC_ASSERT( is_function, enum_type, false ); STATIC_ASSERT( is_function, enum_class_type, false ); STATIC_ASSERT( is_function, struct_type, false ); STATIC_ASSERT( is_function, union_type, false ); STATIC_ASSERT( is_function, mem_data_ptr_type, false ); STATIC_ASSERT( is_function, mem_fun_ptr_type, false ); STATIC_ASSERT( is_function, mem_fun_ptr_type2, false ); STATIC_ASSERT( is_unscoped_enum, arithmetic_type, false ); STATIC_ASSERT( is_unscoped_enum, void_type, false ); STATIC_ASSERT( is_unscoped_enum, lref_type, false ); STATIC_ASSERT( is_unscoped_enum, rref_type, false ); STATIC_ASSERT( is_unscoped_enum, array_type, false ); STATIC_ASSERT( is_unscoped_enum, array_type2, false ); STATIC_ASSERT( is_unscoped_enum, pointer_type, false ); STATIC_ASSERT( is_unscoped_enum, fun_type, false ); STATIC_ASSERT( is_unscoped_enum, pfun_type, false ); STATIC_ASSERT( is_unscoped_enum, fun_ref_type, false ); STATIC_ASSERT( is_unscoped_enum, enum_type, true ); STATIC_ASSERT( is_unscoped_enum, enum_class_type, !ENUM_CLASS_IS_SCOPED ); STATIC_ASSERT( is_unscoped_enum, struct_type, false ); STATIC_ASSERT( is_unscoped_enum, union_type, false ); STATIC_ASSERT( is_unscoped_enum, mem_data_ptr_type, false ); STATIC_ASSERT( is_unscoped_enum, mem_fun_ptr_type, false ); STATIC_ASSERT( is_unscoped_enum, mem_fun_ptr_type2, false ); STATIC_ASSERT( is_scoped_enum, arithmetic_type, false ); STATIC_ASSERT( is_scoped_enum, void_type, false ); STATIC_ASSERT( is_scoped_enum, lref_type, false ); STATIC_ASSERT( is_scoped_enum, rref_type, false ); STATIC_ASSERT( is_scoped_enum, array_type, false ); STATIC_ASSERT( is_scoped_enum, array_type2, false ); STATIC_ASSERT( is_scoped_enum, pointer_type, false ); STATIC_ASSERT( is_scoped_enum, fun_type, false ); STATIC_ASSERT( is_scoped_enum, pfun_type, false ); STATIC_ASSERT( is_scoped_enum, fun_ref_type, false ); STATIC_ASSERT( is_scoped_enum, enum_type, false ); STATIC_ASSERT( is_scoped_enum, enum_class_type, ENUM_CLASS_IS_SCOPED ); STATIC_ASSERT( is_scoped_enum, struct_type, false ); STATIC_ASSERT( is_scoped_enum, union_type, false ); STATIC_ASSERT( is_scoped_enum, mem_data_ptr_type, false ); STATIC_ASSERT( is_scoped_enum, mem_fun_ptr_type, false ); STATIC_ASSERT( is_scoped_enum, mem_fun_ptr_type2, false ); STATIC_ASSERT( is_enum, arithmetic_type, false ); STATIC_ASSERT( is_enum, void_type, false ); STATIC_ASSERT( is_enum, lref_type, false ); STATIC_ASSERT( is_enum, rref_type, false ); STATIC_ASSERT( is_enum, array_type, false ); STATIC_ASSERT( is_enum, array_type2, false ); STATIC_ASSERT( is_enum, pointer_type, false ); STATIC_ASSERT( is_enum, fun_type, false ); STATIC_ASSERT( is_enum, pfun_type, false ); STATIC_ASSERT( is_enum, fun_ref_type, false ); STATIC_ASSERT( is_enum, enum_type, true ); STATIC_ASSERT( is_enum, enum_class_type, true ); STATIC_ASSERT( is_enum, struct_type, false ); STATIC_ASSERT( is_enum, union_type, false ); STATIC_ASSERT( is_enum, mem_data_ptr_type, false ); STATIC_ASSERT( is_enum, mem_fun_ptr_type, false ); STATIC_ASSERT( is_enum, mem_fun_ptr_type2, false ); STATIC_ASSERT( is_mem_data_ptr, arithmetic_type, false ); STATIC_ASSERT( is_mem_data_ptr, void_type, false ); STATIC_ASSERT( is_mem_data_ptr, lref_type, false ); STATIC_ASSERT( is_mem_data_ptr, rref_type, false ); STATIC_ASSERT( is_mem_data_ptr, array_type, false ); STATIC_ASSERT( is_mem_data_ptr, array_type2, false ); STATIC_ASSERT( is_mem_data_ptr, pointer_type, false ); STATIC_ASSERT( is_mem_data_ptr, fun_type, false ); STATIC_ASSERT( is_mem_data_ptr, pfun_type, false ); STATIC_ASSERT( is_mem_data_ptr, fun_ref_type, false ); STATIC_ASSERT( is_mem_data_ptr, enum_type, false ); STATIC_ASSERT( is_mem_data_ptr, enum_class_type, false ); STATIC_ASSERT( is_mem_data_ptr, struct_type, false ); STATIC_ASSERT( is_mem_data_ptr, union_type, false ); STATIC_ASSERT( is_mem_data_ptr, mem_data_ptr_type, true ); STATIC_ASSERT( is_mem_data_ptr, mem_fun_ptr_type, false ); STATIC_ASSERT( is_mem_data_ptr, mem_fun_ptr_type2, false ); STATIC_ASSERT( is_mem_fun_ptr, arithmetic_type, false ); STATIC_ASSERT( is_mem_fun_ptr, void_type, false ); STATIC_ASSERT( is_mem_fun_ptr, lref_type, false ); STATIC_ASSERT( is_mem_fun_ptr, rref_type, false ); STATIC_ASSERT( is_mem_fun_ptr, array_type, false ); STATIC_ASSERT( is_mem_fun_ptr, array_type2, false ); STATIC_ASSERT( is_mem_fun_ptr, pointer_type, false ); STATIC_ASSERT( is_mem_fun_ptr, fun_type, false ); STATIC_ASSERT( is_mem_fun_ptr, pfun_type, false ); STATIC_ASSERT( is_mem_fun_ptr, fun_ref_type, false ); STATIC_ASSERT( is_mem_fun_ptr, enum_type, false ); STATIC_ASSERT( is_mem_fun_ptr, enum_class_type, false ); STATIC_ASSERT( is_mem_fun_ptr, struct_type, false ); STATIC_ASSERT( is_mem_fun_ptr, union_type, false ); STATIC_ASSERT( is_mem_fun_ptr, mem_data_ptr_type, false ); STATIC_ASSERT( is_mem_fun_ptr, mem_fun_ptr_type, true ); STATIC_ASSERT( is_mem_fun_ptr, mem_fun_ptr_type2, true ); }
-
VS 10 mag den Code nicht so sehr:
Microsoft (R) 32-Bit C/C++-Optimierungscompiler Version 16.00.40219.01 für 80x86 Copyright (C) Microsoft Corporation. Alle Rechte vorbehalten. memfn.cpp memfn.cpp(15) : error C2265: 'T': Verweis auf ein Array der Größe Null ist ungültig memfn.cpp(63): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "add_reference<T>". with [ T=array_type2 ] memfn.cpp(49): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "is_reference<T>". with [ T=array_type2 ] memfn.cpp(142): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "is_arithmetic<T>". with [ T=array_type2 ] memfn.cpp(214) : error C2027: Verwendung des undefinierten Typs "assertion_failure<b>" with [ b=false ] memfn.cpp(214) : error C2065: 'value': nichtdeklarierter Bezeichner memfn.cpp(214) : error C2070: ''unknown-type'': Ungültiger sizeof-Operand memfn.cpp(214) : error C2466: Zuordnung eines Arrays der konstanten Größe 0 nicht möglich. memfn.cpp(214) : error C2086: 'int assert__LINE__[1]': Neudefinition memfn.cpp(119): Siehe Deklaration von 'assert__LINE__' memfn.cpp(332) : error C2027: Verwendung des undefinierten Typs "assertion_failure<b>" with [ b=false ] memfn.cpp(332) : error C2065: 'value': nichtdeklarierter Bezeichner memfn.cpp(332) : error C2070: ''unknown-type'': Ungültiger sizeof-Operand memfn.cpp(332) : error C2466: Zuordnung eines Arrays der konstanten Größe 0 nicht möglich. memfn.cpp(332) : error C2086: 'int assert__LINE__[1]': Neudefinition memfn.cpp(119): Siehe Deklaration von 'assert__LINE__' memfn.cpp(350) : error C2027: Verwendung des undefinierten Typs "assertion_failure<b>" with [ b=false ] memfn.cpp(350) : error C2065: 'value': nichtdeklarierter Bezeichner memfn.cpp(350) : error C2070: ''unknown-type'': Ungültiger sizeof-Operand memfn.cpp(350) : error C2466: Zuordnung eines Arrays der konstanten Größe 0 nicht möglich. memfn.cpp(350) : error C2086: 'int assert__LINE__[1]': Neudefinition memfn.cpp(119): Siehe Deklaration von 'assert__LINE__'
-
Etwas geändert, um den ersten Fehler zu beseitigen.
Edit: noch ein paar probleme mit g++ 4.0-4.3 beseitigt (getestet mit 3.4.6, 4.0.4, 4.1.2, 4.2.4, 4.3.6, 4.4.6, 4.5.3, 4.6.3, 4.7.1, 4.8.0 alpha). g++ 3.3.6 kommt offenbar nicht mit dem SFINAE-Trick zurecht.
Die Logik bei Zeigern auf Member wurde geändert. Jetzt funktioniert es vermutlich auch mit vc2010.
-
Okay, kompiliert jetzt auch unter VS 2008:
aber mit warnungen:STATIC_ASSERT( is_scoped_enum, arithmetic_type, false );..\..\..\..\Project\src\Main\Main.cpp(225) : warning C4800: 'arithmetic_type' : forcing value to bool 'true' or 'false' (performance warning)
1> ..\..\..\..\Project\src\Main\Main.cpp(267) : see reference to class template instantiation 'is_convertible<T,U>' being compiled
1> with
1> [
1> T=arithmetic_type,
1> U=bool
1> ]
1> ..\..\..\..\Project\src\Main\Main.cpp(470) : see reference to class template instantiation 'is_scoped_enum<T>' being compiled
1> with
1> [
1> T=arithmetic_type
1> ]
1>..\..\..\..\Project\src\Main\Main.cpp(225) : warning C4800: 'arithmetic_type' : forcing value to bool 'true' or 'false' (performance warning)
1> ..\..\..\..\Project\src\Main\Main.cpp(267) : see reference to class template instantiation 'is_convertible<T,U>' being compiled
1> with
1> [
1> T=lref_type ,
1> U=bool
1> ]
1> ..\..\..\..\Project\src\Main\Main.cpp(472) : see reference to class template instantiation 'is_scoped_enum<T>' being compiled
1> with
1> [
1> T=lref_type
1> ]
-
Bitte noch mal mit der aktuellen Version probieren.
-
Ich hatte meine letzte message editiert, die Warnungen hast du gesehen?
aber hey, sieht nicht schlecht aus, ist das ein kompletter type_traits ersatz für C++03?
Was mir so btw. auffällt ist, das du glaube keine compound typen behandelst,
also z.B.int**** foo;In dem Buch löst er das dadurch, das er das template immer wieder mit sich selbst aufruft.
-
Nash26 schrieb:
Was mir so btw. auffällt ist, das du glaube keine compound typen behandelst,
also z.B.int**** foo;Ohne näher Bezug zum Code zu nehmen, sei hier angemerkt, dass das auch "nur" ein Zeiger ist.
-
Nash26 schrieb:
Ich hatte meine letzte message editiert, die Warnungen hast du gesehen?
aber hey, sieht nicht schlecht aus, ist das ein kompletter type_traits ersatz für C++03?
Was mir so btw. auffällt ist, das du glaube keine compound typen behandelst,
also z.B.int**** foo;In dem Buch löst er das dadurch, das er das template immer wieder mit sich selbst aufruft.
Die Warnung ist harmlos, ich habe aber den Code nochmal geändert, das sollte jetzt ohne diese Warnung compilieren.
Ich habe auch noch mal die Erkennung von Zeigern auf Member geändert, der Workaround zuvor war falsch. Hoffentlich funktioniert das weiterhin mit Visual C++ 2010.
G++ 4.0-4.3 zerlegt Zeiger auf konstante Memberfunktionen in eine Referenz und den Klassenbezug (und hoffentlich ist das auch das Problem bei Visual C++ 2010, dann funktiniert der Workaround). Indem ich jetzt dort (Zeile 92) die Referenz entferne (die dort eigentlich nie auftreten kann, denn Zeiger auf Member verweisen niemals auf Referenzen), funktioniert es jetzt wieder mit allen g++-Versionen ab 3.4.Ich habe auch den Test auf int***** eingebaut (deshalb die vielen typedefs, um leicht mit verschiedenen Typen spielen zu können). Eine rekursive Behandlung ist in der Regel nicht erforderlich.
-
STATIC_ASSERT( is_function, fun_type, true );..\..\..\..\Project\src\Main\Main.cpp(449) : error C2027: use of undefined type 'assertion_failure<b>'
1> with
1> [
1> b=false
1> ]
1>..\..\..\..\Project\src\Main\Main.cpp(449) : error C2065: 'value' : undeclared identifier
1>..\..\..\..\Project\src\Main\Main.cpp(449) : error C2070: ''unknown-type'': illegal sizeof operand
1>..\..\..\..\Project\src\Main\Main.cpp(449) : error C2466: cannot allocate an array of constant size 0
1>..\..\..\..\Project\src\Main\Main.cpp(449) : error C2086: 'int assert__LINE__[1]' : redefinition
1> ..\..\..\..\Project\src\Main\Main.cpp(316) : see declaration of 'assert__LINE__'
1>..\..\..\..\Project\src\Main\Main.cpp(224) : warning C4800: 'fun_type (__cdecl *)' : forcing value to bool 'true' or 'false' (performance warning)
1> ..\..\..\..\Project\src\Main\Main.cpp(185) : see reference to class template instantiation 'is_convertible<T,U>' being compiled
1> with
1> [
1> T=fun_type ,
1> U=bool
1> ]
1> ..\..\..\..\Project\src\Main\Main.cpp(267) : see reference to class template instantiation 'not_<T>' being compiled
1> with
1> [
1> T=is_convertible<fun_type ,bool>
1> ]
1> ..\..\..\..\Project\src\Main\Main.cpp(485) : see reference to class template instantiation 'is_scoped_enum<T>' being compiled
1> with
1> [
1> T=fun_type
1> ]
1>..\..\..\..\Project\src\Main\Main.cpp(539) : error C2027: use of undefined type 'assertion_failure<b>'
1> with
1> [
1> b=false
1> ]
-
Fehler in is_object behoben. Bitte noch mal testen, mit und ohne Compilererweiterungen.
-
1> main.cpp 1>main.cpp(266): error C2027: use of undefined type 'assertion_failure<b>' 1> with 1> [ 1> b=false 1> ] 1>main.cpp(266): error C2065: 'value' : undeclared identifier 1>main.cpp(266): error C2070: ''unknown-type'': illegal sizeof operand 1>main.cpp(266): error C2466: cannot allocate an array of constant size 0 1>main.cpp(266): error C2086: 'int assert__LINE__[1]' : redefinition 1> main.cpp(133) : see declaration of 'assert__LINE__' 1>main.cpp(284): error C2027: use of undefined type 'assertion_failure<b>' 1> with 1> [ 1> b=false 1> ] 1>main.cpp(284): error C2065: 'value' : undeclared identifier 1>main.cpp(284): error C2070: ''unknown-type'': illegal sizeof operand 1>main.cpp(284): error C2466: cannot allocate an array of constant size 0 1>main.cpp(284): error C2086: 'int assert__LINE__[1]' : redefinition 1> main.cpp(133) : see declaration of 'assert__LINE__' 1>main.cpp(43): warning C4800: 'fun_type (__cdecl *)' : forcing value to bool 'true' or 'false' (performance warning) 1> main.cpp(4) : see reference to class template instantiation 'is_convertible<T,U>' being compiled 1> with 1> [ 1> T=fun_type , 1> U=bool 1> ] 1> main.cpp(85) : see reference to class template instantiation 'not_<T>' being compiled 1> with 1> [ 1> T=is_convertible<fun_type ,bool> 1> ] 1> main.cpp(320) : see reference to class template instantiation 'is_scoped_enum<T>' being compiled 1> with 1> [ 1> T=fun_type 1> ] 1>main.cpp(374): error C2027: use of undefined type 'assertion_failure<b>' 1> with 1> [ 1> b=false 1> ] 1>main.cpp(374): error C2065: 'value' : undeclared identifier 1>main.cpp(374): error C2070: ''unknown-type'': illegal sizeof operand 1>main.cpp(374): error C2466: cannot allocate an array of constant size 0 1>main.cpp(374): error C2086: 'int assert__LINE__[1]' : redefinition 1> main.cpp(133) : see declaration of 'assert__LINE__' 1> 1>Build FAILED.Ohne Compilererweiterungen geht's.
-
Swordfish schrieb:
Ohne Compilererweiterungen geht's.
Funktionszeiger können bei Visual C++ implizit in void* konvertiert werden? Wie unsinnig...
Ich habe es nochmal geändert, der ursprüngliche is_function-Code schien ja zu funktionieren.
-
camper schrieb:
Funktionszeiger können bei Visual C++ implizit in void* konvertiert werden?
Ja.
camper schrieb:
Ich habe es nochmal geändert, [...]
Besser.
