Как определить наличие параметра данного типа в списке аргументов переменной функции и действовать после обработки всех параметров
У меня есть следующее 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);
}