2013-03-14 13 views
5

Ho una classe template che definisce alcuni tipi di membri. È simile a come std::map definisce che è value_type basato sui propri argomenti del modello, ma nel mio caso il tipo è più complesso, quindi è definito come classe nidificata.Come sovraccaricare la funzione gratuita per il tipo di membro del modello

Ora per il debug vorrei definire operator<< per quel tipo. Ma il compilatore mi dice che non è possibile dedurre i parametri del template del template esterno.

Il mio codice reale non è artificiosa come il seguente esempio, ma questo esempio inventato dimostra l'approccio che ho provato e come riesce:

#include <iostream> 

template <typename Value> class Outer; 

template <typename Value> 
std::ostream &operator<<(std::ostream &, const typename Outer<Value>::Inner &); 

template <typename Value> 
class Outer { 
    public: 
    struct Inner { 
    Value x; 
    }; 

    void PrintSomething(Value v) { 
    // the real program does something useful with the inner class, of course 
    Inner inner = { v }; 
    std::cout << "Inner = " << inner << std::endl; // <---- THIS SAYS IT CAN'T FIND operator<< 
    }; 
}; 

template <typename Value> 
std::ostream &operator<<(std::ostream &s, const typename Outer<Value>::Inner &v) { 
    return s << v.x; 
} 

int main() { 
    Outer<int> o; 
    o.PrintSomething(42); 
    return 0; 
} 

Questo è campione completo per riprodurre il problema. Il compilatore (ne ho provato 3) dice che non c'è sovraccarico di operator<< che prenderebbe il secondo argomento di tipo Outer<int>::Inner. Quando provo la stessa cosa con funzioni diverse che non hanno altri sovraccarichi, invece dice C2783: could not deduce template argument for 'identifier', gcc e clang continuano a dire che non c'è sovraccarico che prende il secondo argomento Outer<int>::Inner).

Quindi non v'è un modo per definire operator<< prendere Outer<Value>::Inner per qualsiasi Value come è giusto (in modo che non può essere definito come membro) argomento?

Nota: ho bisogno di compilare diversi compilatori e alcuni di essi non hanno alcuna caratteristica di C++ 11, quindi ho bisogno che sia C++ 03.

+0

Ne fanno un amico in linea di 'Inner'. – Xeo

+0

@Xeo: puoi renderlo una risposta? Sembra essere un'idea praticabile. –

+0

Non sono sicuro che tu possa farlo. Vedi [questa domanda] (http://stackoverflow.com/questions/9649904/could-not-deduce-template-argument-pointer-to-member), che è vicino al tuo. – Synxis

risposta

6

Quello che hai è il cosiddetto contesto non deducibile. Come si può dedurre mai Value? Puoi parzialmente specializzare i modelli di classe, rendendo praticamente impossibile per il compilatore persino provare e testare ogni possibile istanziazione (di cui ci sono .. beh, infinito).

Esistono due soluzioni: Take Inner su Outer oppure fare operator<< un amico in linea. Quest'ultimo è il solito modo di andare.

template<class T> 
struct Outer{ 
    struct Inner{ 
    T value; 
    friend std::ostream& operator<<(std::ostream& os, Inner const& v){ 
     return os << v.value: 
    } 
    }; 
    // ... 
}; 
+0

In realtà stavo sovraccaricando non 'operator <<' direttamente, ma una funzione simile specifica alle mie funzioni di logging. E per la normale funzione, l'amico in linea nasconde altri sovraccarichi all'interno della classe, inclusi al suo interno. Quindi ho dovuto usare un po 'di indirezione quando volevo chiamare un sovraccarico diverso su qualcosa all'interno. Ma questo è un ostacolo minore. –

Problemi correlati