Как определить наличие параметра данного типа в списке аргументов переменной функции и действовать после обработки всех параметров

У меня есть следующее operator<<() перегрузка для моего класса с C++17 сгибов:

template <typename... Args>
ostream& operator <<(Args&&... args)
{
    //Currently:
    return (m_osCout << ... << args);

    //What I need:
    IF ANY OF THE parameters in args "was" of type, say TSeek,  
    which can be a manipulator function etc,  then AFTER finishing 
    with the parameter pack, I would like to do some further operation
    , for instance, restore the state of m_osCount
 }

Возможно ли то, что мне нужно, как описано выше? Любые частичные ответы, чтобы установить некоторые направления будут оценены...

Несмотря на то, что я придумал вопрос так, как будто я запрашивал автоматическое восстановление флага потокового потока, обратите внимание, что я придерживаюсь общего решения, а не восстановления std::cout или o / istream восстановление объекта. На практике мой класс является своего рода математическим объектом, который принимает пользовательские типы в качестве аргументов операторов, некоторые из которых требуют функций, подобных манипуляторам ostream, но, как правило, очень и очень неудобно требовать от пользователя предоставления некоторых завершающих операндов перед началом следующего такого использования.

Одна идея, которая пришла мне в голову, состояла в том, чтобы возвратить временный объект другого типа нового умного типа всякий раз, когда TSeek был предоставлен в args... список, так что после того, как последний аргумент будет передан ему, он будет уничтожен автоматически, и это действительно то время, когда я хочу выполнить свою задачу завершения!

Должен ли я поступить так или...?

1 ответ

Решение

Ну... насколько я знаю, поток operator<<() должен получить ровно два аргумента.

Таким образом, вы не можете определить переменную operator<<(),

Если вы принимаете универсальную функцию шаблона variadic, foo() Например, если вы можете использовать C++17, это не очень сложно.

Чтобы проверить наличие типа TSeek в Args... пакет, вы можете написать что-то как

constexpr bool withTSeek { (std::is_same<Args, TSeek>{} || ...) };

Ниже приведен полный пример компиляции

#include <iostream>
#include <utility>
#include <type_traits>

struct TSeek
 { };

std::ostream & operator<< (std::ostream & o, TSeek const &)
 { return o << " [TSeek!] "; }

template <typename ... Args>
std::ostream & foo (std::ostream & o, Args && ... args)
 {
   constexpr bool withTSeek { (std::is_same<Args, TSeek>{} || ...) };

   (o << ... << args);

   if ( withTSeek )
      o << " --- TSeek detected" << std::endl;
   else 
      o << " --- TSeek NOT detected" << std::endl;

   return o;
 }

int main ()
 {
   foo(std::cout, 1, 2, TSeek{}, 5, 7);
   foo(std::cout, 11, 13, 17, 19, 23);
 }
Другие вопросы по тегам