Reputation: 27115
I've started using C++ recently and I've felt a strong urge to
#define print(msg) std::cout << msg << std::endl
Will this perform correctly in all situations? This is the only formulation I'm aware of that will work when there's a <<
in msg (e.g. "foo" << myInt
). Neither
#define print(msg) std::cout << (msg) << std::endl // note: parens
nor the suggested answer
template<typename T>
void print(T const& msg) {
std::cout << msg << std::endl;
}
work in this case. I also don't care about the efficiency of flushing the output with endl
vs just using \n
.
Upvotes: 3
Views: 3698
Reputation: 42574
Just for fun, here's two variadic C++11 implementations of print
: one that inserts spaces between the arguments, and one that does not. (Live at ideone.)
#include <iostream>
namespace with_spaces {
namespace detail {
std::ostream& print(std::ostream& os) {
return os;
}
template <typename T>
std::ostream& print(std::ostream& os, T&& t) {
return os << std::forward<T>(t);
}
template <typename T, typename U, typename... Args>
std::ostream& print(std::ostream& os, T&& t, U&& u, Args&&... args) {
return print(print(os, std::forward<T>(t)) << ' ', std::forward<U>(u), std::forward<Args>(args)...);
}
}
template <typename... Args>
void print(Args&&... args) {
detail::print(std::cout, std::forward<Args>(args)...) << std::endl;
}
}
namespace without {
namespace detail {
std::ostream& print(std::ostream& os) {
return os;
}
template <typename T>
std::ostream& print(std::ostream& os, T&& t) {
return os << std::forward<T>(t);
}
template <typename T, typename... Args>
std::ostream& print(std::ostream& os, T&& t, Args&&... args) {
return print(print(os, std::forward<T>(t)), std::forward<Args>(args)...);
}
}
template <typename... Args>
void print(Args&&... args) {
detail::print(std::cout, std::forward<Args>(args)...) << std::endl;
}
}
#include <iomanip>
int main() {
std::cout << std::boolalpha;
with_spaces::print(1, "foo", new int(3), 0xFFFFFFFFFFULL, 42, 0 == 1);
without::print(1, "foo", new int(3), 0xFFFFFFFFFFULL, 42, 0 == 1);
}
It's interesting to me just how much code is necessary to accomplish what that simple one-line macro can do.
Upvotes: 2
Reputation: 6039
Macros are widely used, but not good practice (especially in C++) because they can hide what is really going on and make it impossible to debug your code.
Macros also bypass the type checking of the preprocessor and can lead to runtime problems.
I would suggest an inline function here if you are trying to optimize for speed.
Upvotes: 0
Reputation: 81379
Since you mention you have just started using C++ recently, I would like to show you a better alternative that the language offers:
template<typename T>
void print(T const& msg)
{
std::cout << msg << std::endl;
}
It takes a single msg
argument of any type, and it streams it out via std::cout
.
As mentioned in the comments, std::endl
does not only insert a new line but also flushes the stream. This is akin to printf
flushing on \n
. If you just want a new line, and you probably do, better do that explicitly:
std::cout << msg << '\n';
Upvotes: 5
Reputation: 96291
This is pretty subjective, but you write code once and read it many times. Other maintainers of the code will want to understand what you've written, so just write std::cout << msg << std::endl
when that's what you mean. Don't try to make C++ look like another language.
Upvotes: 3