2013-03-01 13 views
14

ich einen Zeiger auf ein Klassenelement als Template-Parameter wie in verwenden möchten:Zeiger auf Klassenelement als Template-Parameter

template <class Class, class Result, Result Class::*Member> 
struct MyStruct { 
    // ... 
}; 

diese Struktur verwenden wie MyStruct<SomeClass, SomeResult, &SomeClass::value> variable funktioniert gut, aber ich weiß nicht wie dass ich SomeClass und SomeResult spezifizieren muss.

Ich möchte MyStruct<&SomeClass::value> variable verwenden, wenn das möglich ist, aber ohne die Fähigkeit zu verlieren, irgendeine Klasse zu bestehen und irgendeine Ergebnisart zu haben.

ich folgend versucht, aber die Syntax ist illegal:

template <class Class, class Result> 
template <Result Class::*Member> 
struct MyStruct { 
    // ... 
}; 

error: too many template-parameter-lists

ich mit einer Hilfsfunktion versucht (die tatsächlich in Clang funktioniert aber von GCC zurückgewiesen):

template <class Class, class Result> 
static constexpr auto makeMyStruct(Result Class::*member) -> 
MyStruct<Class, Result, member> { 
    // ... 
} 

error: use of parameter `member' outside function body
error: template argument 3 is invalid

Ist es möglich, eine einfache MyStruct<&SomeClass::value> zu haben, und wenn ja, wie?

Verwandte Frage, die nicht meine Frage lösen:

+0

Dup? http://stackoverflow.com/questions/5628121/is-it-possible-to-emulate-templateauto-x – GManNickG

+0

@GManNickG Ich bin nicht sicher, ob meine Frage auf diese andere Frage läuft. Meins ist viel enger, und ich wäre nicht allzu glücklich mit einem Makro. – kay

+1

Der Begriff ist * Zeiger-zu-Mitglied *, nicht * Verweis * auf Mitglied. Referenzen und Zeiger sind in der Sprache sehr unterschiedlich (na ja, nicht * das * anders, aber immer noch nicht gleich) –

Antwort

2

Diese 11 eine Lösung in C++ sein könnte:

Sie können die folgenden generischen Typen Merkmale definieren:

template<class T> 
struct remove_member_pointer { 
    typedef T type; 
}; 

template<class Parent, class T> 
struct remove_member_pointer<T Parent::*> { 
    typedef T type; 
}; 

template<class T> 
struct baseof_member_pointer { 
    typedef T type; 
}; 

template<class Parent, class T> 
struct baseof_member_pointer<T Parent::*> { 
    typedef Parent type; 
}; 

Jetzt können Sie einen zusätzlichen, 4-line-Wrapper Makro für jede Struktur definieren:

template<class Class, class Result, Result Class::*Member> 
struct _MyStruct { 
    // ... 
}; 

#define MyStruct(MemberPtr) \ 
    _MyStruct<baseof_member_pointer<decltype(MemberPtr)>::type, \ 
      remove_member_pointer<decltype(MemberPtr)>::type, \ 
      MemberPtr> 

... und es auf die folgende Weise verwendet werden:

MyStruct(&SomeClass::value) myStruct; // <-- object of type MyStruct<&SomeClass:value> 

I dies als eine Zwischenlösung zu verwenden, bis wir in C++ 17 wechseln.

+0

Ist nicht die zweite '_MyStruct <'fehl am Platz? – Quentin

+0

@Quentin: Ja, natürlich, danke! ;-) – ManuelAtWork

-6

Sie Ihr Ergebnis Klasse ein Kind Ihrer Template-Klasse. den Zeiger Mitglied angenommen wird in der Öffentlichkeit ein Objekt Ihrer Ergebnisklasse oder was auch immer, können Sie alle Objekte zugreifen, indem Sie so etwas wie diese

template <stuff for this class> :: public result 
{ 
    blah 
} 
11

Eine Antwort auf meine Frage vorgeschlagen wurde in dieser Arbeit für den nächsten C++ Standard zu tun:

Diese Syntax vorgeschlagen wurde:

template<using typename T, T t> 
struct some_struct { /* ... */ }; 

some_struct<&A::f> x; 

Die Notwendigkeit eines neuen syntaktischen Konstrukts weist darauf hin, dass dies jetzt nicht möglich ist.

Ich hoffe, n3601 wird akzeptiert.:-)

5

in C++ 17, mit dem Zusatz von auto in Vorlage Argumenten (P0127), ich glaube, Sie jetzt tun können:

template<auto value> 
struct MyStruct {}; 

template<typename Class, typename Result, Result Class::* value> 
struct MyStruct<value> { 
    // add members using Class, Result, and value here 
    using containing_type = Class; 
}; 

typename MyStruct<&Something::theotherthing>::containing_type x = Something(); 
+0

Dies scheint auf Kling 5.0 zu funktionieren. Https://godbolt.org/g/jc3mSl –