Как определить наличие параметра данного типа в списке аргументов переменной функции и действовать после обработки всех параметров - PullRequest
0 голосов
/ 11 января 2019

У меня следующая перегрузка operator<<() для моего класса с С ++ 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 Ответ

0 голосов
/ 11 января 2019

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

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

Если вы принимаете универсальную шаблонную переменную функцию, 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);
 }
...