2015-03-29 8 views
7

Wie würde ich ein Makro erstellen, das eine variable Anzahl von Argumenten benötigt und es mit std :: cout ausgibt? Entschuldigung, wenn dies eine Frage ohne Frage ist, konnte nichts gefunden werden, was variadische Makros geklärt hat, nachdem man nach der Antwort gesucht hat.Wie mache ich ein variadic Makro für std :: cout?

Conceptual Beispiel:

#include <iostream> 
#define LOG(...) std::cout << ... << ... << std::endl 
int main() { 
    LOG("example","output","filler","text"); 
    return 0; 
} 

ausgeben würde:

exampleoutputfillertext 
+1

Warum? Warum? Warum? schreibe einfach den Code –

Antwort

6

Wenn variadische Makros Sie __VA_ARGS__ müssen alle Argumente erweitern. Das Problem ist jedoch, dass diese Argumente durch Kommas getrennt sind. Vermutlich trennt es nur Argumente zu einem Funktionsaufruf, aber da Makros nur mit Text arbeiten, können Sie auch __VA_ARGS__ in anderen Kontexten verwenden, wo eine kommagetrennte Liste sinnvoll ist.

Der Trick, den Sie verwenden können, ist Ihre eigene Komma-Operator für std::ostream (die Art der std::cout) zu definieren. Zum Beispiel:

#include<iostream> 
#define LOG(...) std::cout , __VA_ARGS__ , std::endl 

template <typename T> 
std::ostream& operator,(std::ostream& out, const T& t) { 
    out << t; 
    return out; 
} 

//overloaded version to handle all those special std::endl and others... 
std::ostream& operator,(std::ostream& out, std::ostream&(*f)(std::ostream&)) { 
    out << f; 
    return out; 
} 

int main() { 
    LOG("example","output","filler","text"); 
    return 0; 
} 

Nun wird die LOG Aufruf erweitern:

std::cout , "example" , "output" , "filler" , "text" , std::endl; 

und die Kommas werden die überladene Komma Operatoren aufrufen.

Wenn Sie nicht überladen operator, alle std::ostream -s verschmutzen möchten, können Sie std::cout mit Ihrer eigenen speziellen Logger-Klasse verkapseln.

+0

ist nicht '__VA_ARGS__' gcc-spezifisch? – vsoftco

+3

Meines Wissens '__VA_ARGS__' wird in jedem C/C++ - Compiler unterstützt, der Variadic-Makros in erster Linie unterstützt. Variadische Makros sind Standard in C und C++ 11, aber nicht in C++. – CygnusX1

+0

danke, wusste nicht, dass sie es in C++ 11 schaffen. auf den Punkt Antwort, upvoted – vsoftco

1

Nicht sicher gibt es eine Möglichkeit, ein Variadic-Makro in C++ zu definieren (zumindest nicht portabel). Warum verwenden Sie keinen variadischen Vorlagenansatz? Etwas wie

#include <iostream> 

void LOG() {} 

template<typename Head, typename... Args> 
void LOG(const Head& head, const Args&... args) 
{ 
    std::cout << head << " "; 
    LOG(args...); 
} 

int main() 
{ 
    LOG("This", "is" , "the", 3, "rd test"); 
} 
+0

Sie benötigen eine Abbruchbedingung, um zu verhindern, dass diese Vorlage unendlich rekursiv ist. – Peter

+0

@Peter das ist, was die 'void LOG()' tut – vsoftco

13

Sie benötigen keine Präprozessor-Makros, um dies zu tun. Sie können es in normalen C++ schreiben:

#include <iostream> 
#include <utility> 

void log(){} 

template<typename First, typename ...Rest> 
void log(First && first, Rest && ...rest) 
{ 
    std::cout << std::forward<First>(first); 
    log(std::forward<Rest>(rest)...); 
} 

int main() 
{ 
    log("Hello", "brave","new","world!\n"); 
    log("1", 2,std::string("3"),4.0,'\n'); 
} 

Ausgang:

Hellobravenewworld! 
1234 

Sie variadic templates und parameter packs statt variadische Makros erforschen sollte, die in der modernen C selten nützlich sind ++.

(gcc 4.9.2 -std = C++ 11)

+0

Okay! Danke für den Hinweis. Der Code ist ziemlich genial :-) – BlurryZombie

+0

@BlurryZombie Gern geschehen.Der Code ist völlig normal. Sie müssen nur etwas über die Funktionen lernen, die ich erwähnt habe. –

Verwandte Themen