2013-09-16 1 views
5

У меня есть следующие настройки:оператор перегрузки << для шаблона вложенного класса

template< class T > 
struct Foo { 

    struct Bar { 
    Bar (const T &t) : otherT_(t) {} 

    T otherT_; 
    }; 

    Foo (const T &t) : myT_(t) {} 

    T myT_; 
}; 

Теперь я хочу, чтобы экземпляры Foo<T>::Bar поточных в StD :: COUT и друзьям. Я попытался это:

template< class T > 
std::ostream& operator<< (std::ostream &os, 
          const typename Foo<T>::Bar &bar) { 
    os << "<bar: " << bar.otherT_ << ">"; 
    return os; 
} 

Но следующий код не компилируется:

Foo<int> foo(5); 
    Foo<int>::Bar bar(7); 

    std::cout << bar << std::endl; 

Я предполагаю, что компилятор не может вывести тип T или что-то. Есть ли способ сделать такие экземпляры вложенного класса хорошо себя вести с operator<<?

Спасибо!

+1

Copy/Paste [этот ответ] (http://stackoverflow.com/a/18823636/596781)? –

+0

@KerrekSB Итак, ответ заключается в том, что просто невозможно написать 'std :: cout << bar'? Или я могу сделать однозначное сопоставление, указанное в связанном ответе, явным? – Sh4pe

+1

@KerrekSB Я не уверен, что следую приведенному ответу. Причина для его ошибки проста: 'T' в' Foo :: Bar' невыводимый контекст, см. §14.8.2.5/5. Как и другие, указали , что делает работу с другом (потому что полученная функция не является шаблоном, поэтому не требуется никакого вывода типа). –

ответ

9

Да, легкий способ поставить operator<< внутри Bar:

struct Bar { 
    Bar (const T &t) : otherT_(t) {} 

    T otherT_; 

    friend std::ostream& operator<< (std::ostream &os, const Bar &bar) 
    { 
    os << "<bar: " << bar.otherT_ << ">"; 
    return os; 
    } 
}; 

Я рыть другой путь ...

+1

+1 за то, что он быстрее :) – jrok

+0

:) все еще пробовал другой способ :) – Raffi

+0

который другим способом? – TemplateRex

3

Обход - определить operator<< как друга внутри определения Bar «s:

template< class T > 
struct Foo { 

    struct Bar { 
    Bar (const T &t) : otherT_(t) {} 

    T otherT_; 

    friend std::ostream& operator<< (std::ostream &os, const Bar &bar) 
    { 
     os << "<bar: " << bar.otherT_ << ">"; 
     return os; 
    } 

    }; 

    Foo (const T &t) : myT_(t) {} 

    T myT_; 
}; 

Проблема с вашим подходом заключается в том, что, как сказал в комментариях KerrekSB, T не может быть выведено. Существует, возможно, бесконечное число T для Foo<T>::Bar, каждый из которых может привести к другому типу.

1

Компилятор не может вывести T, однако, когда вы делаете его другом, он находит его через ADL.

Я изменил код к следующему:

#include <iostream> 
using namespace std; 

template< class T > 
struct Foo { 

struct Bar { 
Bar (const T &t) : otherT_(t) {} 

T otherT_; 
friend std::ostream& operator << (std::ostream& os, const Bar &bar) 
{ return os; } 
}; 

Foo (const T &t) : myT_(t) {} 


T myT_; 
}; 

int main() { 
Foo<int> foo(5); 
Foo<int>::Bar bar(7); 

std::cout << bar << std::endl; 
return 0; 
}