2013-03-01 13 views
14

voglio usare un puntatore a un membro della classe come parametro di template come in:puntatore a membro della classe come parametro di template

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

Utilizzando questa struct come MyStruct<SomeClass, SomeResult, &SomeClass::value> variable funziona bene, ma non mi piace che devo specificare SomeClass e SomeResult.

Vorrei utilizzare MyStruct<&SomeClass::value> variable se ciò è possibile, ma senza perdere la possibilità di passare alcuna classe e avere alcun tipo di risultato.

Ho provato quanto segue, ma la sintassi è illegale:

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

error: too many template-parameter-lists

Ho provato ad utilizzare una funzione di supporto (che funziona veramente in Clang, ma viene rifiutato da GCC):

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

e 'possibile avere un semplice MyStruct<&SomeClass::value>, e se sì, come?

questione connessa che non ha risolto la mia domanda:

+0

Dup? http://stackoverflow.com/questions/5628121/is-it-possibile-per-e-mulare-templateauto-x – GManNickG

+0

@GManNickG Non sono sicuro se la mia domanda si riduce a quell'altra domanda. Il mio è molto più stretto, e non sarei troppo contento di usare una macro. – kay

+1

Il termine è * puntatore-a-membro *, non * riferimento * al membro. Riferimenti e puntatori sono abbastanza diversi nella lingua (beh, non * che * diverso, ma non è lo stesso) –

risposta

2

Questa potrebbe essere una soluzione in C++ 11:

È possibile definire i seguenti tratti di tipo generico:

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; 
}; 

Ora è possibile definire un ulteriore, 4 righe involucro macro per ogni struct:

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> 

... e utilizzarlo nel seguente modo:

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

uso questo come una soluzione intermedia, finché si passa a C++ 17.

+0

Non è il secondo '_MyStruct <' fuori luogo? – Quentin

+0

@Quentin: Sì, certo, grazie! ;-) – ManuelAtWork

-6

Fai la tua classe risultato un bambino della classe template. assumendo il membro puntatore è un oggetto della classe risultato in pubblico o qualsiasi altra cosa, è possibile accedere a qualsiasi oggetto facendo qualcosa di simile

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

una risposta alla mia domanda è stata proposta in questo lavoro per il prossimo imminente standard C++:

Questa sintassi è stato proposto:

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

some_struct<&A::f> x; 

La necessità di un nuovo costrutto sintattico indica che non è possibile farlo ora.

Spero che n3601 sia accettato.:-)

5

in C++ 17, con l'aggiunta di auto negli argomenti di template (P0127), penso che ora si può fare:

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

Sembra funzionare su clang 5.0 https://godbolt.org/g/jc3mSl –