В краце хочеться, чтобы каждый стрим мог форматировать данные как ему хочеться. Но в момент, когда начинается форматирование у меня есть только ссылка на базовый стрим.
Понятно, что приведенный код работать не будет: в базом классе нет нужного operator <<.
Добавить его в базовый класс и сделат виртуальным тоже не получиться, так как он параметризован.
Есть ли возможность это как-то обойти? Или может есть стандартные приемы для подобных случаев?
N>В краце хочеться, чтобы каждый стрим мог форматировать данные как ему хочеться. Но в момент, когда начинается форматирование у меня есть только ссылка на базовый стрим.
N>Понятно, что приведенный код работать не будет: в базом классе нет нужного operator <<. N>Добавить его в базовый класс и сделат виртуальным тоже не получиться, так как он параметризован.
N>Есть ли возможность это как-то обойти? Или может есть стандартные приемы для подобных случаев?
Ну насколько я понимаю, через интерфейс базового класса можно вызвать только методы в нём (интерфейсе) определённые. Если хочется вызывать методы наследников, то приводи тип, используя dynamyc_cast.
EG>Ну насколько я понимаю, через интерфейс базового класса можно вызвать только методы в нём (интерфейсе) определённые. Если хочется вызывать методы наследников, то приводи тип, используя dynamyc_cast.
Ну вот у меня есть два потомка-стрима в примере super_stream и another_super_stream. К какому из них приводить?
В момент начала форматирования тип неизвестен
Но, к сожалению (а может к счастью), шаблонные виртуальные функции не предусмотрены в С++ стандартом.
Поэтому в общем виде эта задача не решается, прийдется искать решение для более частных случаев.
Posted via RSDN NNTP Server 2.0
--
Справедливость выше закона. А человечность выше справедливости.
R>"Nickolas" <116@users.rsdn.ru> wrote in message news:1811985@news.rsdn.ru... >> Всем привет. Есть вот такой код:
R>Эта задача решалась бы, если бы можно было объявить basic_stream так:
R>
R>Но, к сожалению (а может к счастью), шаблонные виртуальные функции не предусмотрены в С++ стандартом. R>Поэтому в общем виде эта задача не решается, прийдется искать решение для более частных случаев.
довольно дурацкий подход с кучей проблем... попробуй пересмотреть концепт кардинально... например сделать классы formatterов способных выводить в стрим (любой, а не только cout) что тебе там требуеца...
в результате запись буит примерна такой:
* форматилки получают в конструкторе то чего нада выводить (конструкторы при этом могут быть шаблонные)
* форматилки сами могут быть шаблонными
* все форматилки наследники интерфейса некой "абстрактной форматилки" имеющей спец функцию для вывода в стрим
* есь перегруженый оператор вывода абстрактной форматилки в стрим вызывающий указанную виртуальную функцию...
это все может дать мегагибкость...
однако я не телепат и более точные условия задачи не помешали бы... (вместа попытки решить твою конкретную проблему с парой классов)
N>Есть ли возможность это как-то обойти? Или может есть стандартные приемы для подобных случаев?
Для начала надо вспомнить что параметризировать клиенский код можно не только средствами динамического полиморфизма но и на основе статического
N>Понятно, что приведенный код работать не будет: в базом классе нет нужного operator <<. N>Добавить его в базовый класс и сделат виртуальным тоже не получиться, так как он параметризован.
Нам не нужен базовый класс, нам нужна полиморфная функция, написанная единожды и работающая с разными типами
N>В краце хочеться, чтобы каждый стрим мог форматировать данные как ему хочеться.
Предлагаю рассмотреть возможное решение на основе CRTP (curiously recurrent template pattern)
Здравствуйте, Nickolas, Вы писали:
N>Ну вот у меня есть два потомка-стрима в примере super_stream и another_super_stream. К какому из них приводить? N>В момент начала форматирования тип неизвестен
Если функция, которую ты собираешься вызвать определена во всех классах — потомках, то, возможно, следует вынести ее в отдельный класса — интерфейс, от которого и наследовать super_stream и another_super_stream.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Nickolas, Вы писали:
N>>Есть ли возможность это как-то обойти? Или может есть стандартные приемы для подобных случаев? А>Для начала надо вспомнить что параметризировать клиенский код можно не только средствами динамического полиморфизма но и на основе статического
N>>Понятно, что приведенный код работать не будет: в базом классе нет нужного operator <<. N>>Добавить его в базовый класс и сделат виртуальным тоже не получиться, так как он параметризован. А>Нам не нужен базовый класс, нам нужна полиморфная функция, написанная единожды и работающая с разными типами
N>>В краце хочеться, чтобы каждый стрим мог форматировать данные как ему хочеться. А>Предлагаю рассмотреть возможное решение на основе CRTP (curiously recurrent template pattern)
А в какой момент позовется выделенный оператор? И для чего он вообще тут нужен?
Никогда!. Ваша правда, приведенный пример это не демонстрирует.
Для начала исправим ошибку
template <typename T>
struct basic_stream
{
template <typename U>
std::ostream& operator << (U v) // must be U instead of T
{
return static_cast<T&>(*this).operator<<(v);
}
};
Но все это, ИМХО, надумано и с точки зрения применимости практически равно нулю.
Использование CRTP здесь явно ни к месту, просто избавляемся от basic_stream<...> и в итоге имеем
А>Спасибо за коммент, хоть кто-то разобрался до конца
Я не то, чтобы не разобрался в Вашем примере, просто это решение мне не совсем подходит.
template <typename T>
struct basic_stream
{
template <typename U>
std::ostream& operator << (U v) // must be U instead of T
{
return static_cast<T&>(*this).operator<<(v);
}
};
Для меня важно, чтобы basic_stream был не параметризован, так как он используется как параметр в некоторых виртуальных методах.
Но всеравно огромное Вам спасибо — Ваше решение навело меня на некоторые полезные мысли
Здравствуйте, Nickolas, Вы писали:
N>В краце хочеться, чтобы каждый стрим мог форматировать данные как ему хочеться. Но в момент, когда начинается форматирование у меня есть только ссылка на базовый стрим.
Страуструп в таком случае предлагает следующий подход: