operator<< дла класса вложенного в шаблонный
От: Аноним  
Дата: 27.12.09 21:02
Оценка:
Всем доброго времени суток.

Есть такая проблема, не могу перегрузить оператор << в такой ситуации:

template <typename T> class C
{
};

template <template <class> class T> class A
{
    public:
        class B
        {
            int c;
        };

        C<A> c;
        B b;

        void f()
        {
            std::ostringstream s;
            s << b;
        }
};


имеется ввиду оператор для A::B. Пытаюсь написать так:


template <template <class> class T> std::ostringstream& operator<<(std::ostringstream& _s, typename A<T>::B& _v)
{
    _s << "";
    return _s;
}


Компилятор (gcc 4.4.1) не находит подходящей функции для операции s << b. Причем описанной выше функции нет в кандидатах.
Как в таком случае можно перегрузить operator<< ?

29.12.09 14:04: Перенесено модератором из 'C/C++. Прикладные вопросы' — Кодт
Re: operator<< дла класса вложенного в шаблонный
От: Vladimir V. Alekseev  
Дата: 27.12.09 23:23
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Всем доброго времени суток.


А>Есть такая проблема, не могу перегрузить оператор << в такой ситуации:


... skiped ...

А>имеется ввиду оператор для A::B. Пытаюсь написать так:


... skiped ...

А>Компилятор (gcc 4.4.1) не находит подходящей функции для операции s << b. Причем описанной выше функции нет в кандидатах.

А>Как в таком случае можно перегрузить operator<< ?

Как исправить в данном случае operator<< — затрудняюсь сказать. А нельзя ли поправить f()? Если вынести описание этого метода за класс и написать после описания шаблонного operator<< вот таким образом:

template< template<class> class T>
void A<T>::f()
{
    operator<< <T>(std::cout,b);
}


То все компилируется и работает.
Re: operator<< дла класса вложенного в шаблонный
От: remark Россия http://www.1024cores.net/
Дата: 28.12.09 06:47
Оценка: 52 (2)
Здравствуйте, Аноним, Вы писали:

А>Компилятор (gcc 4.4.1) не находит подходящей функции для операции s << b. Причем описанной выше функции нет в кандидатах.

А>Как в таком случае можно перегрузить operator<< ?

Может так прокатит...

template <template <class> class T> class A
{
    public:
        class B
        {
            int c;
            friend std::ostream& operator<<(std::ostream& s, B const& v)
            {
               return s << "";
            }            
        };
};



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: operator<< дла класса вложенного в шаблонный
От: Аноним  
Дата: 28.12.09 09:42
Оценка:
Здравствуйте, remark, Вы писали:

Спасибо!
Re: operator<< дла класса вложенного в шаблонный
От: Caracrist https://1pwd.org/
Дата: 29.12.09 11:33
Оценка:
Здравствуйте, Аноним, Вы писали:


как уже обяснили мне тут
Автор: Caracrist
Дата: 27.12.09
. Template Deduction не работает на вложенные типы если обращение к ним пришлось писать с ключём typename. Соответственно всё что к ним должно приводится должно быть написанно там где непосредственно видино сам вложенный тип/typedef.
~~~~~
~lol~~
~~~ Single Password Solution
Re: operator<< дла класса вложенного в шаблонный
От: rg45 СССР  
Дата: 29.12.09 14:49
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Всем доброго времени суток.


А>Есть такая проблема, не могу перегрузить оператор << в такой ситуации:

А>
А>template <typename T> class C
А>{
А>};

А>template <template <class> class T> class A
А>{
А>    public:
А>        class B
А>        {
А>            int c;
А>        };
А>        C<A> c;
А>        B b;
А>        void f()
А>        {
А>            std::ostringstream s;
А>            s << b;
А>        }
А>};
А>

А>Как в таком случае можно перегрузить operator<< ?

Вынести класс B наружу и не париться. Вложенность классов без веских на то оснований — порочная практика.
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: operator<< дла класса вложенного в шаблонный
От: rg45 СССР  
Дата: 29.12.09 15:53
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Аноним, Вы писали:


А>>Компилятор (gcc 4.4.1) не находит подходящей функции для операции s << b. Причем описанной выше функции нет в кандидатах.

А>>Как в таком случае можно перегрузить operator<< ?

R>Может так прокатит...


R>
R>template <template <class> class T> class A
R>{
R>    public:
R>        class B
R>        {
R>            int c;
R>            friend std::ostream& operator<<(std::ostream& s, B const& v)
R>            {
R>               return s << "";
R>            }            
R>        };
R>};
R>


R>


Гм, занятный обходной маневр получается: в 14.8.2.4/9 перечислены формы параметров шаблонных функций, которые должен уметь выводить компилятор:

T
cv-list T
T*
T&
T[integer-constant]
template-name<T> (where template-name refers to a class template)
type(*)(T)
T(*)()
T(*)(T)
T type::*
type T::*
T T::*
T (type::*)()
type (T::*)()
type (type::*)(T)
type (T::*)(T)
T (type::*)(T)
T (T::*)()
T (T::*)(T)
type[i]
template-name<i> (where template-name refers to a class template)
TT<T>
TT<i>
TT<>

А с помощю предложенной техники мы этот список как бы расширяем еще одной формой:
T::type

Где type — имя вложенного типа, определенного внутри T (не typedef). Т.е. можно-таки решать уравнения по выведению обрамляющего типа!
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: operator<< дла класса вложенного в шаблонный
От: pzhy  
Дата: 29.12.09 18:19
Оценка:
Здравствуйте, remark, Вы писали:

R>Может так прокатит...


R>
R>template <template <class> class T> class A
R>{
R>    public:
R>        class B
R>        {
R>            int c;
R>            friend std::ostream& operator<<(std::ostream& s, B const& v)
R>            {
R>               return s << "";
R>            }            
R>        };
R>};
R>


R>


Хм... Занятная конструкция. Только я не очень понимаю чем вообще является подобного рода функция.
если написать например так:

class A
{
    public:
        friend void f()
        {
        }
};


То функцию f() мне не удалось ниоткуда вызвать. Т.е. это может делать только компилятор (в применении к operator<<)?
Что это вообще такое? Как, например, будет выглядеть, тип указателя на такую функцию, если он вообще возможен?
Re[3]: operator<< дла класса вложенного в шаблонный
От: rg45 СССР  
Дата: 29.12.09 20:12
Оценка:
Здравствуйте, pzhy, Вы писали:

P>Хм... Занятная конструкция. Только я не очень понимаю чем вообще является подобного рода функция.

P>если написать например так:

P>
P>class A
P>{
P>    public:
P>        friend void f()
P>        {
P>        }
P>};
P>


P>То функцию f() мне не удалось ниоткуда вызвать.


А так попробуй:
#include <iostream>
#include <string>

template <typename T>
struct A
{
  struct Inner { T value; };
  friend void f(const Inner& inner) { std::cout << inner.value << std::endl; }
};

int main()
{
  A<std::string>::Inner inner = { "Hello, World !!!" };
  f(inner);
}
--
Справедливость выше закона. А человечность выше справедливости.
Re[3]: operator<< дла класса вложенного в шаблонный
От: Николай Ивченков  
Дата: 29.12.09 20:27
Оценка: +1
rg45:

R>Гм, занятный обходной маневр получается: в 14.8.2.4/9 перечислены формы параметров шаблонных функций, которые должен уметь выводить компилятор:


R>А с помощю предложенной техники мы этот список как бы расширяем еще одной формой:

R>
R>T::type
R>

R>Где type — имя вложенного типа, определенного внутри T (не typedef). Т.е. можно-таки решать уравнения по выведению обрамляющего типа!

Здесь нет вывода типа, т.к. определение

friend std::ostream& operator<<(std::ostream& s, B const& v)
{
   return s << "";
}

с каждым инстанцированием шаблона A порождает определение обычной функции (не шаблона).
Re[3]: operator<< дла класса вложенного в шаблонный
От: Николай Ивченков  
Дата: 29.12.09 20:28
Оценка:
pzhy:

P>если написать например так:


P>
P>class A
P>{
P>    public:
P>        friend void f()
P>        {
P>        }
P>};
P>


P>То функцию f() мне не удалось ниоткуда вызвать.


Это потому, что friend declaration вводит в пространство имён функцию, не видимую при unqualified name lookup и qualified name lookup. В данном случае т.к. у функции нет никаких параметров, то очевидно, что и через argument-dependent name lookup она искаться не будет. Единственный способ сделать её видимой — это добавить обычное объявление:

#include <iostream>

class A
{
    public:
        friend void f()
        {
            std::cout << "f()" << std::endl;
        }
};

int main()
{
    void f(); // <--
    f();
}

В остальном это обычная свободная функция.
Re[4]: operator<< дла класса вложенного в шаблонный
От: rg45 СССР  
Дата: 29.12.09 20:32
Оценка:
Здравствуйте, Николай Ивченков, Вы писали:

НИ>с каждым инстанцированием шаблона A порождает определение обычной функции (не шаблона).


Это понятно, но, тем не менее, снаружи, с точки зрения использующего кода очень похоже на то, как будто выполняется выведение типа.
--
Справедливость выше закона. А человечность выше справедливости.
Re[5]: operator<< дла класса вложенного в шаблонный
От: rg45 СССР  
Дата: 29.12.09 21:15
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, Николай Ивченков, Вы писали:


НИ>>с каждым инстанцированием шаблона A порождает определение обычной функции (не шаблона).


R>Это понятно, но, тем не менее, снаружи, с точки зрения использующего кода очень похоже на то, как будто выполняется выведение типа.


Сейчас я попытаюсь оформить свою мысль более разборчиво.

Если у нас есть следующее определение шаблонного класса:
template <typename T>
struct A
{
  struct Inner { T value; };
};

и мы хотим поиметь свободную функцию f, которую можно будет вызывать так:
  A<int>::Inner i = { 123 };
  A<double>::Inner d = { 1.23 };
  A<std::string>::Inner s = { "Hello, World !!!" };
  f(i);
  f(d);
  f(s);

то нам прийдется для каждого типа, которым мы параметризуем шаблонный класс A, завести для f отдельную перегрузку:
void f(const A<std::string>::Inner& inner) { std::cout << inner.value << std::endl; }
void f(const A<int>::Inner& inner) { std::cout << inner.value << std::endl; }
void f(const A<double>::Inner& inner) { std::cout << inner.value << std::endl; }

Что, очевидно, не совсем удобно.

Как только мы попытаемся выполнить обобщение в виде шаблонной функции:
template <typename T>
void f(const typename A<T>::Inner& inner) { std::cout << inner.value << std::endl; }

мы сразу же потеряем возможность автовыведения типов шаблонной функции f. Т.к. согласно 14.8.2.4/9 форма A<T>::Inner не подлежит автовыведению. Т.е. вызовы шаблонной функции f будут возможны только при явной спецификации шаблонного параметра:
  f<int>(i);
  f<double>(d);
  f<std::string>(s);


Если же мы воспользуемся техникой, предложенной remark-ом, то мы и избавимся от необходимости определять отдельную перегрузку f для каждого типа в отдельности, и при этом вызовы f не потребуют дополнительной спецификации шаблонного параметра:

#include <iostream>
#include <string>

template <typename T>
struct A
{
  struct Inner { T value; };
  friend void f(const Inner& inner) { std::cout << inner.value << std::endl; }
};

int main()
{
  A<int>::Inner i = { 123 };
  A<double>::Inner d = { 1.23 };
  A<std::string>::Inner s = { "Hello, World !!!" };
  f(i);
  f(d);
  f(s);
}

Т.е. суммарный эффект получаем такой, как если бы компилятор умел выводить обрамляющий тип по вложенному.
--
Справедливость выше закона. А человечность выше справедливости.
Re[3]: operator<< дла класса вложенного в шаблонный
От: Caracrist https://1pwd.org/
Дата: 30.12.09 08:53
Оценка:
Здравствуйте, pzhy:


 namespace td
 {
     template<typename T>
     T & deduct(T&t) 
     {
         return t;
     }
 }
 struct SA
 {
     class inner {public: int i; };
     inner inn;
     friend inner& ::td::deduct<inner>(inner& in);
 };

int _tmain(int argc, _TCHAR* argv[])
{
    SA sa; //Warning    1    warning C4101: 'sa' : unreferenced local variable
    int intt = deduct(sa.inn);
        intt ++; //Warning    2    warning C4700: uninitialized local variable 'intt' used    
// Run-Time Check Failure #3 - The variable 'intt' is being used without being initialized.
        return 0;
}


VS2008SP1
~~~~~
~lol~~
~~~ Single Password Solution
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.