Overloading streaming on the Arduino - c++

Please RTFM me if needed, as so far I may have been searching for the wrong things!
On the Arduino
Serial << "sdf" << var;
works a treat (with streaming.h referenced), but
#if (CRIPWEB_DEBUG_BITS & DEBUG_CMD)
Serial << F("Run Macro: ") << strMacro << "\n";
#endif
takes three lines and makes the code unreadable.
I'd like to say something along the lines of:
Debug(CRIPWEB_DEBUG_BITS & DEBUG_CMD) << F("Run Macro: ") << strMacro << "\n";
Is this possible? I'd be happier with:
Debug.set(CRIPWEB_DEBUG_BITS & DEBUG_CMD); Debug << F("Run Macro: ") << strMacro << "\n";
I'll worry about size after I've had a go at this!
Many thanks,
Glyn

The preprocessor would be compile-time, the other would not. You really want the slowdown?
Anyway, if you accept a slightly different syntax, we get pretty near to what you wanted while not giving up on eliminating the useless code at compile-time:
#define COND(cond, ...) ((void)((exp) && (__VA_ARGS__, 0)))
Use as
COND(CRIPWEB_DEBUG_BITS & DEBUG_CMD, Serial << F("Run Macro: ") << strMacro << "\n");
Or, if you only ever test that one condition:
#define IFDEBUG(...) ((void)((CRIPWEB_DEBUG_BITS & DEBUG_CMD) && (__VA_ARGS__, 0)))
Use as
IFDEBUG(Serial << F("Run Macro: ") << strMacro << "\n");

You could write your own class to do exactly that.

I am answering only compile-time solution for the expression:
Serial << "sdf" << var;
Assume Serial is a global instance of class. Let's say instance of class DebugWriter. This class has overloaded operator <<. Now, you can make another class FakeDebugWriter, which will also have operator << implemented, but that would do nothing. Further, you can declare Serial instance as:
#if CRIPWEB_DEBUG_BITS & DEBUG_CMD
DebugWriter Serial;
#else
FakeDebugWriter Serial;
#endif
But it should be noted that Serial<< will still make call to function in case of FakeDebugWriter - though compiler may omit out the function call.
Therefore, it would be better to write debug-logging as function-style macro only. You can craft the macro has do some thing (or something heavy), and another as Do-nothing.
EDIT: After comment from OP. Here is analogues similar example.
SmallInt a, b;
Where SmallInt would be type-defined, depending on value(s) of pre-processor macro (not macro macro).
#if SomeCondition
typedef int SmallInt;
#else
typedef short SmallInt;
#endif

Related

How to use Macros in c++?

Recently I came across inline in c++17 and how it been used as an alternative to #define but both have its downsides. However my question is that if I want to cramp the whole std::cout << x << '\n'; in one simple line called LOG(x).
A: What should I use and why?
B: What are the pros and cons of each and when to use what?
1.)
#define LOG(x) std::cout << x << '\n'
2.)
void inline LOG(auto x)
{
std::cout << x << '\n';
}
3.)
void LOG(auto x)
{
std::cout << x << '\n';
}
4.)
This one was suggested to me by someone:
template <typename T>
void log(const T& x)
{
std::cout << x << '\n';
}
How to use Macros in c++?
Sparingly. When there is no better alternative.
Avoid this. Macros names don't respect scoping rules and thus are much more susceptible to name clashes. Also, consider what happens if you wanted to log a number bitshifted by another number:
LOG(0x1 << 2);
What output would you expect, and what output do you get? Do they match?
Pro: It is a function (template) and thus doesn't have the problems associated with macros. Con: You accept the parameter by value. This can be expensive with for example strings which are quite often used for logging. Requires C++20.
Practically identical to 2. The auto parameter turns these into function templates which are implicitly inline.
Pro: Doesn't require C++20. A reference is passed, which is good for passing strings.
In conclusion: 4. is a reasonable default choice.
The general consensus is that using macros is not a good idea. BUT what that really means is that ABUSE of macros is not a good idea.
Solution #2 is OK, but its usefulness is rather limited, since you can only print one value per line.
inline void LOG(const auto& x)
{
std::cout << x << '\n';
}
// use as:
LOG(x);
And it's an OK solution, but its usage is rather limited.. Consider this use case:
inline void LOG(const auto& x)
{
std::cout << x << '\n';
}
struct point { float x, y; };
// usability is kind of limited, since it will only print one value per line
point p{};
LOG(x);
LOG(y);
// which gives this output.
0
0
// That's not really useful for a log.
One advantage of the macro, is that you could make your log output a bit more useful.
#define LOG(x) std::cout << x << '\n'
struct point { float x, y; };
// usability is better, but still limited,
point p{};
LOG("x: " << p.x << ", y: " << p.y);
// which gives this output.
x: 0, y: 0
That's a bit better, you are using a macro, and you do have more control over the output, making your log more useful. But it puts some limitations on your code... For example, you may want, at a later date, to use a third party logging library, or write your own, but some calls to LOG() will have operators in them, and this may force you to rewrite them.
For this reason, among others, a function template would be better, one that accepts any number of arguments.
template <typename... Args>
inline void LOG(Args&&... args)
{
(std::cout << ... << args) << '\n';
}
point p{};
LOG("x: ", p.x, ", y: ", p.y);
// which gives this output.
x: 0, y: 0
If you want to defeat logging in your release version, I suggest using a macro.
#define LOG(...)
// on MSVC
#define LOG(...) __noop
I wouldn't use #1 (macro version) unless you want to log the symbol name of the variable in the output, such as:
#define LOG(x) std::cout << #x << " = " << x << '\n'
I believe #2 and #4 are equivalent, as using auto introduces a template type under the hood.
#3 is slightly inferior as it requires you to write a declaration in a header file as well as putting the definition in a source file (since it is not inline), which is more code to maintain.

C++ preprocessor conditional parameter

Please note C++03! any C++11 solutions are not good for me, but do post them just for knowledge sake.
I know the preprocessor can do things like:
#define FOO 4
#if FOO == 4
cout<<"hi"<<endl;
#endif
What I need is:
#define BAR(X)\
#if X == 4\
cout<<"hi"<<endl;\
#endif
main.cpp
BAR(4)
I don't see why all the needed information wouldn't be available in preprocessor time.
So, Please tell me how to achieve this kind of behavior.
edit 1:
A normal if condition won't work for my case, because I also do things like:
#define BAR(X)\
#if X == 4\
int poop;
#elif
double poop;
#endif
As you've discovered, you can't do this in the way that you've attempted. Macro expansion simply doesn't have inline conditional evaluation, so you'd have to create multiple macros instead.
However, if you're just trying to "optimise" normal code flow, you can rely on your compiler's optimizations. Consider this:
if (true) {
std::cout << "Hi\n";
}
The resulting program will not have any conditional checks in it, because true is always truthy.
Similarly:
if (false) {
std::cout << "Hi\n";
}
The resulting program will not contain any code to produce output, because false is never truthy.
Similarly:
if (4 != 4) {
std::cout << "Hi\n";
}
The program will still not contain the std::cout code.
In many cases, you may use this fact to keep your code simple and achieve your desired effect:
#define BAR(X) \
if ((X) == 4) {
std::cout << "hi" << std::endl;\
}
The constraint here, of course, is that an if statement must be valid at the place you write BAR(5), or BAR(42) or BAR(999).
This is also flexible in that now you can use a runtime value (like BAR(i)) and, although the conditional can no longer be collapsed at compile-time, in such a case you'd have no reason to expect that anyway.
I take this approach in my logging macro: the macro, when called for LOG_LEVEL_DEBUG, expands to a conditional that is statically known never to match, in release builds.
The idea is to let the compiler do the optimising.
You're also going to want to consider using a little macro expansion trick to avoid problems with subsequent else clauses.
You can do this with the preprocessor if the domain of values for the conditional parameter is well-known (and preferably small). For example, supposing the parameter can only have the values 0 and 1:
#define DOIT_0(X)
#define DOIT_1(X) X
#define CONCAT_(X, Y) X ## Y
#define MAYBE(X) CONCAT_(DOIT_, X)
#define BAR(X) MAYBE(X)( cout<<"hi"<<endl; )
#define YESNO 0
BAR(YESNO)
Live on coliru.
Beware of unprotected commas in the argument to BAR.
For equality checks, again over a small range:
#define CONCAT3_(X,Y,Z) X ## Y ## Z
#define EQUAL_0_0(X) X
#define EQUAL_1_1(X) X
#define EQUAL_1_1(X) X
#define EQUAL_0_1(X)
#define EQUAL_0_2(X)
#define EQUAL_1_0(X)
#define EQUAL_1_2(X)
#define EQUAL_2_0(X)
#define EQUAL_2_1(X)
#define DO_IF_EQUAL(X, Y) CONCAT3_(EQUAL_, X, Y)
#define BAR(X) DO_IF_EQUAL(X, 2) ( std::cout << "hi\n"; )
If you can use Boost, you could do this with Boost.Preprocessor:
#define BAR(X) BOOST_PP_EXPR_IF(BOOST_PP_EQUAL(X, 4), cout << "hi" << endl;)
Some answers here were better than others.
The one I accepted was posted by Christian Kiewiet in a comment, but it was the most accurate for my purpose.
Here is the expanded version:
useCases.h
enum UseCases{
useCase1=0,
useCase2,
useCaseNumber//always last for iterations
}
specializer.h
#include "useCases.h"
<template UseCases theCase>
struct StaticCase{
//empty, thus accidents calling from this can't happen
}
//specialization
template<>
class StaticCase<UseCases::useCase1>{
typedef int T;
static foo(T arg){cout<<"case1";};
}
template<>
class StaticCase<UseCases::useCase2>{
typedef double T;
static foo(){cout<<"case2";};
}
Now, I can do
#define BAR1(useCase) StaticCase<useCase>::foo();
or
#define BAR2(useCase) StaticCase<useCase>::T var;
and the call:
BAR1(UseCases::useCase1)//output - case1
BAR1(UseCases::useCase2)//output - case2

Replace std::cout with a define

I try to force my compiler to replace any std::cout occurrence in my code with something.
But when I write something like that:
#define std::cout (*some code*)
My compiler spit on my face. Is there a way to do this ?
EDIT :
Here is the code snippet:
# define std::cout (std_out << std::cout)
(std_out is a file I've previously open)
and the error on a line with a std::out occurence
the global scope has no "cout"
You define an identifier, not an arbitrary expression. std is
an identifier; your define will cause the compiler to replace
every instance of the identifier std with ::cout (*some
code*). So it's not surprising that the compiler doesn't like
it: std::cout << toto becomes ::cout (*some code*)::cout <<
toto and std::vector becomes ::cout (*some code*)::vector.
If you'd explain what you're actually trying to achieve, we could probably help you better.
I try to force my compiler to replace any std::cout occurence in my code with something
That's a bad idea. If you are looking for configurable behavior on your output stream, replace all occurrences of std::cout in your code with out, and declare out as std::ostream& out (= whatever stream type you may need).
My compiler spit on my face. Is there a way to do this ?
Not as such. No. You could write:
#define OUTPUT std::cout
OUTPUT << "a = " << a << std::endl;
but you needing a #define to disable (or redirect) your output stream is a sign of bad design (i.e. your define is not the problem you should be trying to solve).
You can make your own version of cout, that actually calls cout, you can place any custom code there:
std::ostream& my_cout() {
/// ...
return std::cout << "a custom message";
}
int main() {
my_cout() << " hi" << std::endl;
}

Why can't I add to a ostringstream outside a method/function

If I use this code outside of a method or winmain:
ostringstream vertexid;
vertexid << "bob";
vertexid << " ";
vertexid << " ";
vertexid << 48348093490;
I get all sorts of syntax errors. How does scope play into this why is this happening?
You can do something like this:
std::ostringstream ss;
#define nil(x) ((x), 0)
int x = nil(ss << "Hello");
int y = nil(ss << ", World!");
int z = nil(ss << std::endl);
If you really don't like thinking up variable names, then you can do something even crazier:
#define nilPASTE(x, y) x ## y
#define nilPASTE2(x, y) nilPASTE(x, y)
#define nil2(x) static int nilPASTE2(line_, __LINE__) = nil(x)
nil2(ss << "Goodbye");
nil2(ss << ", Sun!");
nil2(ss << std::endl);
You asked:
How does scope play into this why is this happening?
I assume you mention scope because that is what some error message spat out. But the answer to both parts of that question is that the C++ compiler is following the rules of the C++ language, which does not allow statements to just appear anywhere. They can only appear where they are allowed, which are in functions and method bodies. The reason my technique is allowed is because I am using expressions, and expressions can appear in more places. In particular, they are allowed to appear in an initializer to a variable. And of course, variable declarations are allowed on the outer most level of a translation unit.
All that gobbly gook means: put your statements inside functions and methods.
You can only declare or define stuff at global scope.
The first line alone would be OK (in an implementation file... if in a header, you risk having multiple definitions and would need to declare it as extern instead of defining it), the next lines are just not legal.
At global namespace you cannot have code, because when should it be executed? You can only put executable statements inside functions, for example WinMain/main.
The execution starts at WinMain/main, then you can call your other functions from there.

C++ Getting the size of a type in a macro conditional

Is there some way to do something like this in c++, it seems sizeof cant be used there for some reason?
#if sizeof(wchar_t) != 2
#error "wchar_t is expected to be a 16 bit type."
#endif
No, this can't be done because all macro expansion (#... things) is done in the pre-processor step which does not know anything about the types of the C++ code and even does not need to know anything about the language!
It just expands/checks the #... things and nothing else!
There are some other common errors, for example:
enum XY
{
MY_CONST = 7,
};
#if MY_CONST == 7
// This code will NEVER be compiled because the pre-processor does not know anything about your enum!
#endif //
You can only access and use things in #if that are defined via command line options to the compiler or via #define.
The preprocessor works without knowing anything about the types, even the builtin one.
BTW, you can still do the check using a static_assert like feature (boost has one for instance, C++0X will have one).
Edit: C99 and C++0X have also WCHAR_MIN and WCHAR_MAX macros in <stdint.h>
I think things like BOOST_STATIC_ASSERT could help.
Wouldn't you get basically what you want (compile error w/o the fancy message) by using a C_ASSERT?
#define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
sizeof() is a runtime compile-time function. You cannot call that in a preprocessor directive. I don't think you can check the size of wchar_t during preprocessing. (see Edit 2)
Edit: As pointed out in comments, sizeof() is mostly calculated at compile time. In C99, it can be used at runtime for arrays.
Edit 2: You can do asserts at build time using the techniques described in this thread.
char _assert_wchar_t_is_16bit[ sizeof(wchar_t) == 2 ? 1 : -1];
I've developed some macros that will effectively allow you to use sizeof within a macro condition. They're in a header file that I've uploaded here (MIT license).
It will permit for code like this:
#include <iostream>
#include "SIZEOF_definitions.h"
//You can also use SIZEOF_UINT in place of SIZEOF(unsigned, int)
// and UINT_BIT in place of SIZEOF_BIT(unsigned, int)
#if SIZEOF(unsigned, int) == 4
int func() { return SIZEOF_BIT(unsigned, int); }
#elif SIZEOF(unsigned, int) == 8
int func() { return 2 * SIZEOF_BIT(unsigned, int); }
#endif
int main(int argc, char** argv) {
std::cout SIZEOF(unsigned, long, int) << " chars, #bits = " << SIZEOF_BIT(unsigned, long, int) << '\n'
<< SIZEOF(unsigned, int) << " chars, #bits = " << SIZEOF_BIT(unsigned, int) << '\n'
<< SIZEOF(int) << " chars, #bits = " << SIZEOF_BIT(int) << '\n';
std::cout << func() << std::endl;
return 0;
}
Note the commas within SIZEOF(unsigned, long, int).