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?

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top