Simple Macro program I think

Post the complete code your tried and the complete error message verbatim.

You should do this each and every time. Even then if you only changed a single character.
You should post your complete sketch for two reasons:

  1. eliminating any room for interpretation where you modified the code
  2. for convenience of all other users. Because when code is posted as a code-section you can move the mouse to the upper-right corner of the code-section and copy the complete sketch into the clipboard with a single mouseclick.

Code-sections have a limited height. So you can even post code with 3000 lines of code without using much space on the screen.

The template is what its name says: a template that shows the compiler what you want to do

So writing down this part of the code is essential to make it work
taken from user @kenb4

template <typename T, typename ... Remainder>
void printMany(T first, Remainder ... remainder) {
  Serial.print(first);
  Serial.print(' '); // comment out if desired
  printMany(remainder...);
}

So all in all you need to add all these lines to your existing code

the definition of the function printMany() and the definition of the template
template <typename T, typename ... Remainder>.....

void printMany() {
  Serial.println(); // blank line after other arguments (if any)
}
template <typename T, typename ... Remainder>
void printMany(T first, Remainder ... remainder) {
  Serial.print(first);
  Serial.print(' '); // comment out if desired
  printMany(remainder...);
}

This reminds me a bit of functional programming like LISP where you are operating recursively on a list which has a head (which they called CAR) and tail (CDR). The tail itself has a head and a (smaller) tail so the list is a naturally recursive construct. However, there it is done dynamically at runtime. Also most of it I have forgotten. With the C++ template construct it appears it is almost like a compile time text editing operation to rollout a copy for each recursive iteration.

You need not. First, it's our time to spend or waste as the case may be. Second, you are not the only one reading this thread, and hoping to learn something every day we visit.

Learn or at least be exposed to.

Another thing it reminds me of is assembly language macro processors. When exploited by the wizards they can do all kinds of things… compute N!, play a decent game of tic-tac-toe with the user and so forth. Oh how they rolled back in the day. :expressionless:

And it seems like the germ of an idea that landed up with modern templates.

a7

Okay, here's the entire error msg followed by the sketch.

sketch_may01a:5: error: variable or field 'printMany' declared void

void printMany(T first, Remainder ... remainder) {
^
sketch_may01a:5: error: 'T' was not declared in this scope

sketch_may01a:5: error: 'Remainder' was not declared in this scope

void printMany(T first, Remainder ... remainder) {
^
exit status 1
variable or field 'printMany' declared void

void printMany() {
  Serial.println(); // blank line after other arguments (if any)
}
template <typename T, typename ... Remainder>
void printMany(T first, Remainder ... remainder) {
  Serial.print(first);
  Serial.print(' '); // comment out if desired
  printMany(remainder...);
}

void setup() {
  Serial.begin(115200);
  delay(1000);

  float f {3.14};
  uint8_t u16 {10};
  int16_t i16 { -5001};
  const char str[] {"Hello World"};

  printMany(f, u16, i16, str);
  printMany(f, u16, i16);
  printMany(f, u16);
  printMany(f);
  printMany();
  Serial.println("done");
}
void loop() {
  // put your main code here, to run repeatedly:

}

That code compiles error-free for me. Are you sure it's the exact, complete code that caused the compilation error? Are there any other .ino, .h, or .cpp files in the project?

What Arduino board are you compiling for?

You should also include the complete compiler log.
Here is a tutorial how to adjust the arduino IDE for maximum verbose compiler-log.
This compiler log will answer these questions:

gfvalvo

No other files in the project, a brand new sketch.
The board is a wemos D1 mini (esp8266). I tried an Arduino Mega/Mega 2560 board with the same error results.

My IDE is 1.8.5.

The sketch is exactly as in my last msg, no changes. I tried again making sure to copy the sketch in your post #4 and got the same errors.

Thanks, Frank

Uh wow. Pretty old. This version makes your computer vulnerable through the log4j-java security-gap

I highly recommend that you update to version 1.8.19

There is a possability to have a completely independant second Arduino IDE as a portable version

For an Arduino Mega it should compile immidiately after installing
You will have to install the ESP8266 package for ESP8266 support.

Anyway maybe the reason might be the super old Arduino IDE and or an old ESP8266 package.

What is so hard about following the compiler-log tutorial and then posting the complete compiler-log?

There is no way around posting this verbose compiler-log !

I have taken your code from post # 26 and pasted into a WOKWI-Demo that compiles just fine.

So without a much more detailed information about YOUR computers configuration which will be delivered by the verbose compiler-log
we can't help you !

StefanL38
Thank you.
My current IDE is the portable version and I agree it's pretty old. Back around 2020 I tried a later version and discovered that my sketches needed some changes to work. I decided then not to bother, but that was 4 years ago. I supose I should bite the bullet now and upgrade. I guess I can keep both versions and gradually migrate sketches as needed.

At the moment my disk space is full. I have been fighting a losing battle trying to clear space for the last week or so and I finally ordered a new drive today.

I do have my above Macro that satisfiers my needs for now and I want to continue working on that related sketch so It will be a while before I get back to this issue.

Incidentally I copied the code from my sketch into the WOKWI-Demo and like you said it worked perfectly, very slick sketch. I then tried to run it on an esp32 and the compile failed with lots of error messages. It may have been something I did as I have no clue how to configure that system. Or maybe that failure is indicative of my esp8266 related problem.

Anyway, I hear you about the verbose complier log. I'll do that in the future.

BTW, I would normally assume 1.8.19 is older than my 1.8.5 version.

Thanks Again to all,
Frank

which number is higher "5" or "19" ?

1.8.19 is the last version of Arduino IDE 1.X
After 1.8.19 comes Arduino IDE 2.X
I still use IDE 1.8.19 because IDE 2.X has so many bells and whistles that I don't need
and in V2.X the serial monitor is crippled down to be almost unusable.

Sounds like you are using a pretty old computer.
How about updating to a lenovo Thinkpad T480 or L580 with intel-processor generation 8?
Not older because generation 7 and older has no support under Windows 11.
There is software available to make Windows 11 look and feel like windows 7.

As a leasing-returner they are about $200.

StefanL38
Without much thought conventional math says .5 is higher then .19, my bad. I do know better.

Yes, my computer is a little old using W10 with an I5 processor, still okay for my needs.

I've been using refurnished $100-$200 computers for years, never been sorry.

BTW, I'm really a hardware guy who at age 35 designed and built my first computer in 1975 from discrete components around an RCA microprocessor. There wasn't much software back then and I had to write my own assembler. Started with 256 bytes of memory and a bunch of toggle switches. Eventually grew to 4k memory with the video section of a TV for a monitor. With all that history it's a wonder I can think at-all. I will say, it's a whole different world today.

Thank you.
Frank

I don't think the issue you're having has anything to do with the age of your computer or which version of the Arduino IDE you're using. Variadic Templates (the technique I posted) were introduced with C++11. Every board support package for every flavor of Arduino board out there supports at least C++11. In fact, it's really on the cores for AVR-based boards that are stuck on C++11. Most others use C++17 or later.

You're experiencing some kind of installation or configuration issue. Unfortunately, not being a very knowledgeable tool chain guy, I'm unable to provide guidance in that area.

If the IDE is old, there maybe an issue with the preprocessor creating unwanted function prototypes, which could explain the odd behaviour. This seems to get better with each attempt to fix it but will always be vulnerable to exotic constructs.

Good point, I forgot about that. I've seen issue with templates in the main .ino with earlier IDE versions. Moving them to a .h fixed it. IMO the auto prototype generator was a mistake from the beginning. Folks should have simply been introduced to supplying their own function prototypes early on.

@frank2644, I know you're happy (enough) with your macro solution and are probably ready to move on. But, per @6v6gt's post, there's one more thing you might try. Break my example code into two files and see if it will compile.

Main .ino File:

#include "Header.h"

void setup() {

  Serial.begin(115200);
  delay(1000);

  float f {3.14};
  uint8_t u16 {10};
  int16_t i16 { -5001};
  const char str[] {"Hello World"};

  printMany(f, '\n', u16, ", ", i16, "\n\n... ", str, '\n');
}

void loop() {
}

Header.h:

#ifndef HEADER_H
#define HEADER_H

#include <Arduino.h>

template <typename T>
void  printMany(T arg) {
  Serial.print(arg);
}

template <typename T, typename ... Remainder>
void  printMany(T first, Remainder ... remainder) {
  Serial.print(first);
  printMany(remainder...);
}

#endif

Don't get me started on the "prototype generation feature". I've said (nearly) all I want to say on that in various posts and conclude that, at least with .ino files, we simply have to live with it as a "sin from the past". I hope only that this mess is an object lesson for future developers who would even consider "improving" the C++ language by a series of backdoor hacks. Fortunately, this "feature" is restriced to .ino files so experienced users can soon find a work around.

However, having said that, I will take the opportunity of undermining one of the key pillars on which this debacle was built, that is the desire to protect new users from the otherwise well understood and basic principle that program variables etc. have to be declared before being used. Take the "multiple .ino" scenario. A user may build an application by combining multiple .ino files. These are consolidated into a single file based on alphabetical sort order of file name. The user will come to experience that variables declared in files with names lower in the alphabetical sorting order have a higher likelihood of being available throughout the application than those declared in files with a correspondingly higher alphabetical name ranking.

In general, however, I must now say that I consider these as minor blemishes on an otherwise well conceived and implemented philosophy which has very successfully brought microcontrollers to the masses.

imho the simplest solution is to stream elements.
Streaming can be used for all outputs which inherit Print.h .
These are the HW Serials, SoftSerial, webclients, lot of LCD libraries and many more.


#include <Streaming.h>

void setup() {
  Serial.begin(115200);
  delay(1000);

  float f {3.14};
  uint8_t u16 {10};
  int16_t i16 { -5001};
  const char str[] {"Hello World"};

  Serial << f << u16 << i16 << str << F("fixtext") << endl;

}

void loop() {
  // put your main code here, to run repeatedly:

}

include the Streaming library,
instead of print use <<
when you want to end a line stream endl

gfvalvo,

Thanks,
That worked! Compiled and executed as expected.

BTW, I improved my related macro as follows:
#define printMany(arg1,arg2,arg3,arg4) Serial.print(arg1); Serial.print(arg2);Serial.print(arg3);Serial.print(arg4);

using AutoHotkey pressing F2 puts this into my sketch: printMany("","","","");

Then I simply put up to 4 parms where the quote marks are located. If I use say only one parm the unused args do no harm as double quotes without an intervening char apparently do nothing. Of course the macro can be expanded to 5 or more args if that is helpful.

So I have taken some of the inconvenience out of my macro solution. Your solution is better, but with my limited knowledge I hesitate to use something I do not understand. Maybe in the future as I gain knowledge I may be more comfortable using it.

Thanks again
Frank

noiasca,

Thanks, I never knew about streaming till now. That could come in handy in the future.

Actually, my problem involves calling a custom function not capable of accepting streaming. I decided to use Serial.print in my sudo code to simplify my question.

Thanks again,
Frank