2016-06-30 1 views
2

Je souhaite déclarer une fonction qui écrit par défaut sur std::out, mais qui permet également d'écrire dans un autre flux de sortie, le cas échéant. Par exemple:std :: ostream comme paramètre de fonction optionnel (!)

print_function(std::string & str, 
       std::ostream & out = std::cout, 
       std::ostream & other = nullptr) // <-- how to make it optional??? 
{ 
    out << str; 
    if (other == something) // if optional 'other' argument is provided 
    { 
     other << str; 
    } 
} 

Réglage nullprt ne fonctionne évidemment pas, mais comment cela peut-il être fait?

+0

connexes: http://stackoverflow.com/questions/11826554/standard-no-op-output-stream – lorro

+2

Il me semble que ce serait beaucoup plus naturel d'avoir deux, l'une avec des surcharges deux arguments, et un avec trois arguments. – Hurkyl

+1

@Hurkyl: ou en gardant celui avec 2 arguments et en passant un "tee_stream'". – Jarod42

Répondre

1

Je voudrais simplement utiliser la surcharge de fonction, plutôt que des arguments par défaut

// declare the functions in a header 

void print_function(std::string &str); 
void print_function(std::string &str, std::ostream &ostr); 
void print_function(std::string &str, std::ostream &ostr, std::ostream &other); 

// and in some compilation unit, define them 

#include "the_header" 

void print_function(std::string &str) 
{ 
     print_function(str, std::cout); 
} 

void print_function(std::string &str, std::ostream &ostr) 
{ 
    // whatever 
} 

void print_function(std::string & str, 
        std::ostream &ostr, 
        std::ostream &other) 
{ 
    print_function(str, ostr); 

    other << str; 
} 

Les trois versions de ces fonctions peuvent faire tout ce que vous aimez. Selon vos besoins, tout peut être mis en œuvre en utilisant les autres. Si vous avez besoin d'entrelacer la logique dans les trois fonctions (par exemple les instructions affectant other doivent être entrelacées avec les instructions de l'une des autres fonctions), alors introduisez des fonctions auxiliaires pour implémenter la logique dans des parties séparées, plus granulaires.

+0

C'est peut-être la solution la plus simple et directe, qui ne nécessite pas non plus de boost. – Stingery

7

avec pointeur, ou boost::optional

void print_function(std::string & str, 
       std::ostream & out = std::cout, 
       std::ostream* other = nullptr) 
{ 
    out << str; 
    if (other) 
    { 
     *other << str; 
    } 
} 

ou

void print_function(std::string & str, 
       std::ostream & out = std::cout, 
       boost::optional<std::ostream&> other = boost::none) 
{ 
    out << str; 
    if (other) 
    { 
     *other << str; 
    } 
} 
+1

Je garderais l'approche 'boost :: optional' seulement ... Ou au moins avant l'approche du pointeur. – Nawaz

+1

@Nawaz: Certains ne veulent pas que la dépendance booste :-(. Donc jusqu'à ce que 'optional' soit dans' 'std ::' ... – Jarod42

+0

Références optionnelles où j'ai été exclu de la dernière version de std – Yakk

1

Vous pouvez utiliser boost::optional ou pointeur, comme suggested by @Jarod42. Cependant, les deux approches vous forcent à utiliser des instructions conditionnelles dans le corps de la fonction.

Voici une autre approche dont l'avantage est la simplicité du corps de la fonction:

void print_function(std::string & str, 
       std::ostream & out = std::cout, 
       std::ostream& other = null_stream) 
{ 
    out << str; 
    other << str; //no "if" required here. 
} 

Et voici comment vous pouvez définir l'objet null_stream:

#include <boost/iostreams/stream.hpp> 
#include <boost/iostreams/device/null.hpp> 

boost::iostreams::stream<boost::iostreams::null_sink> null_stream { 
      boost::iostreams::null_sink{} 
}; 

Ici null_stream est un std::ostream qui ne rien. Il y a other ways pour l'implémenter aussi.

Espérons que ça aide.