Espressione operatore modello di sovraccarico problema con std :: vector
-
28-09-2019 - |
Domanda
Al momento sto lavorando su una biblioteca numerica che i modelli di uso di espressione. Purtroppo ho incontrato un problema con i miei overload dell'operatore. Si consideri il seguente esempio ridotta.
#include <vector>
namespace test {
class test {};
template<class A, class B>
class testExpr {};
template<class A, class B>
testExpr<A, B>
operator-(A a, B b)
{
return testExpr<A, B>();
}
}
test::test
stuff(std::vector<test::test> &v)
{ return v.back(); }
int main()
{ }
che dà il seguente messaggio di errore quando si compila con gcc 4.4.3 o clang 2.8:
In file included from eir_test.cc:2:
In file included from /usr/include/c++/4.4/vector:64:
/usr/include/c++/4.4/bits/stl_vector.h:696:16: error: indirection requires pointer operand
('testExpr<__gnu_cxx::__normal_iterator<test::test *, std::vector<test::test, std::allocator<test::test> > >, int>' invalid)
{ return *(end() - 1); }
^~~~~~~~~~~~
eir_test.cc:21:12: note: in instantiation of member function 'std::vector<test::test, std::allocator<test::test> >::back' requested here
return v.back();
^
1 error generated.
Per qualche ragione i compilatori fare una ricerca nello spazio dei nomi di prova e trovare il mio operatore generale. Ho usato questo modulo insieme con qualche magia tratti di ridurre il numero di versione ho dovuto fare per l'operatore. Dovrebbe accettare 4 tipi di dati diversi (tra cui doppie e int) che porterebbe ad un sacco di combinazioni diverse.
C'è un modo per fare questo lavoro senza precisando tutte le combinazioni per tutti gli operatori?
Soluzione
Questo perché end()
restituisce un tipo che è una specializzazione del modello di classe che ha un argomento di tipo test::test *
. Così, quando operator-
si applica nel end() - 1
espressione, argomento sguardi di ricerca dipendenti anche nello spazio dei nomi di test::test
. Essa trova il tuo operator-
e lo passa l'iteratore e un int
.
Si potrebbe risolvere il problema, non accettando qualsiasi e tutti i tipi come argomenti. Ad esempio, provare ad accettare (testExpr<A1, B1>, testExpr<A2, B2>)
invece. Mostra tutte le combinazioni, forse c'è un modo per tagliare giù utilizzando un altro modo per formulare loro?
A mio parere, un'implementazione che agisce in questo modo dovrebbe essere non conforme (credo che questo è davvero disgustoso però). Perché fare iterator - 1
è specificato a cedere un altro iteratore all'elemento precedente e non deve fare qualcosa di pazzo del genere, credo. Un modo per esso è dichiarare operatore come un non-template accettando il tipo iteratore e l'argomento intero (che è difference_type
dell'iteratore) direttamente. In questo modo la loro versione deve essere sempre preferito.
Altri suggerimenti
Il codice compilato OK in VC ++ versione 10 (da Visual Studio 2010 C ++ espresso), anche se modificato in questo modo:
int main()
{
vector<test::test> vec;
test::test instance = stuff(vec);
return 0;
}
Questa potrebbe essere una limitazione dei compilatori. modelli di espressioni sono un po 'di un test di stress per il supporto modello di un compilatore.