c++ error messages

Example C++ code with error messages

I’ve been working a bit with GNU C/C++ (version 11.3) on Linux Mint 21. I’ve been trying to use Visual Studio Code for coding, thinking that it, along with Microsoft’s extension, would help me write more effectively by pointing out problems/errors and providing suggested solutions. Sometimes that works, sometimes it doesn’t, meaning that I get the error but no idea how to solve it, no clues whatsoever. Rather, if I take the problematic code and let GNU C++ try to compile it, I get very verbose errors that include helpful suggestions on how to correct the problem.

This post uses a very simple program that requires C++ in order to compile and execute. Here’s the correct listing.

#include <iostream>#include <iterator>int main(int argc, char *argv[]) {std::copy(argv, argv + argc, std::ostream_iterator<char *>(std::cout, "\n"));}

It’s just six lines of code (five if you ignore the whitespace). The key line is line 5, a one-liner that prints out all the arguments passed along to the application when it’s called, one argument/line. I didn’t create this, but I learned it decades ago and have kept it in my “back pocket” along with many other bits of proven and useful code.

The problem occurred in another application when I failed to include a library that required an iterator definition. I eventually fixed it, but only on the command line using GNU’s C++. I then whipped up this example to show what I’m complaining about. If you look at the top screen capture you’ll see that VS Code has put red squiggles underneath the problem code. I’ve deliberately used an ostream_iterator that calls out for the inclusion of the iterator library. Unfortunately, as you’ll note above, clicking on the bad code in VS Code does nothing more than state the obvious. No clue how you might fix this. And before you say anything, I’ve worked with other IDEs in the past that actually did offer suggestions, and even offered to fix it for you. For example, Android Studio and the IDE it was derived from, JetBrains’ IntelliJ IDE. Granted those tools are all about Java and Kotlin, but still, they’re a lot more helpful and productive.

In the end it was GNU’s C++ that provided all I needed to fix the contrived problem.

cli.cpp: In function ‘int main(int, char**)’:cli.cpp:5:39: error: ‘ostream_iterator’ is not a member of ‘std’5 | std::copy(argv, argv + argc, std::ostream_iterator<char *>(std::cout, "\n"));  |   ^~~~~~~~~~~~~~~~cli.cpp:2:1: note: ‘std::ostream_iterator’ is defined in header ‘<iterator>’; did you forget to ‘#include <iterator>’?1 | #include <iostream>  +++ |+#include <iterator>2 | //#include <iterator>

This help included not only what library definition to include, but where (yes, I commented out the original to break it). Line five in the error listing shows you where ostream_iterator is defined, and line 7 helpfully shows you where to place the include in your code. This kind of compiler help reminds me of the help that Rust’s compiler also produces when it comes across a problem.

My experience with C++ goes back to 1986 when it was first called C with Classes and you had to run cfront on your C++ code to produce C code that was then compiled and linked. All this on a Micro VAX running Ultrix, DEC’s version of BSD Unix (which was nothing more than bog-standard BSD with all the licensing text replaced with DEC). I know it’s so much fun denigrating C++, but it’s evolving to answer the critiques and the needs of its users, both in the language as well as the tooling.

simple programming of the esp32-s3-devkitc-1 using esp-idf, version 2

ESP32-S3-DevKitC-1 with externally wired LED — drawn with KiCad 6

I’ve been cleaning up some code, and I decided to go back and do a smidge of refactoring of the original post. So here’s the new code. Comments on what changed and why follows.

#include <stdio.h>#include "freertos/FreeRTOS.h"#include "freertos/task.h"#include "driver/gpio.h"#include "esp_log.h"#include "led_strip.h"#include "sdkconfig.h"#include <vector>#include <tuple>typedef std::tuple<int, int, int, int> led_color;const std::vector <led_color> colors {{0,32,0,0},  // red{0,0,32,0},  // green{0,0,0,32},  // blue{0,0,32,32}, // cyan{0,32,0,32}, // magenta{0,32,16,0}, // yellow{0,0,0,0}// black};// Task 1.//static void task_blink_neo_pixel(void * pvParameters) {static led_strip_t *pStrip_a;pStrip_a = led_strip_init(CONFIG_BLINK_LED_RMT_CHANNEL, CONFIG_BLINK_GPIO, 1);pStrip_a->clear(pStrip_a, 50);// Stay in an endless loop. Don't return from this task.//while(true) {for(led_color c : colors) {pStrip_a->set_pixel(pStrip_a,std::get<0>(c), std::get<1>(c), std::get<2>(c), std::get<3>(c));pStrip_a->refresh(pStrip_a, 100);vTaskDelay(500 / portTICK_PERIOD_MS);// Set NeoPixel LED dark by clearing all its individual LEDs.pStrip_a->clear(pStrip_a, 50);vTaskDelay(500 / portTICK_PERIOD_MS);}}}// Task 2.//static void task_blink_led(void * pvParameters) {gpio_reset_pin(GPIO_NUM_46);// Set the GPIO as a push/pull output//gpio_set_direction(GPIO_NUM_46, GPIO_MODE_OUTPUT);// Stay in an endless loop. Don't return from this task.//while (true) {gpio_set_level(GPIO_NUM_46, true);   // LED onvTaskDelay(100 / portTICK_PERIOD_MS);gpio_set_level(GPIO_NUM_46, false);  // LED offvTaskDelay(100 / portTICK_PERIOD_MS);gpio_set_level(GPIO_NUM_46, true);   // LED onvTaskDelay(100 / portTICK_PERIOD_MS);gpio_set_level(GPIO_NUM_46, false);  // LED offvTaskDelay(2700 / portTICK_PERIOD_MS);}}extern "C" void app_main(void) {static const char *TAG = "DUAL_BLINK";int core = xPortGetCoreID();ESP_LOGI(TAG, "app_main running on core %i", core);ESP_LOGI(TAG, "CONFIG_BLINK_GPIO %i", CONFIG_BLINK_GPIO);// Create task 1.//TaskHandle_t xHandle1 = NULL;static uint8_t ucParameterToPass1 = 1;xTaskCreate(task_blink_neo_pixel,"BlinkNeoPixel",// human readable task name.2048,   // stack size in bytes.&ucParameterToPass1,tskIDLE_PRIORITY,&xHandle1);configASSERT(xHandle1);// Create task 2.//TaskHandle_t xHandle2 = NULL;static uint8_t ucParameterToPass2 = 1;xTaskCreate(task_blink_led,"BlinkLED", // human-readable task name.2048,   // stack size in bytes.&ucParameterToPass2,tskIDLE_PRIORITY,&xHandle2);configASSERT(xHandle2);// Stay in an endless loop. Don't return from this task.//while (true) {vTaskDelay(1000 / portTICK_PERIOD_MS);}}

Here’s what changed.

  • ESP-IDF was updated to version 4.4.3. I’m using that now, waiting in anticipation of the version 5.0.0 drop. Version 5 is now a release candidate, but I’m holding off stepping up to that until there’s a full formal release.
  • The source file was renamed to dualblink.cpp. That cpp extension signals to the tool chain to treat this as a C++ source file, with all that implies. This allowed me to include vector and tuple (lines 18 and 19), which then provided me with a better way to define the collection of colors to cycle through in the task_blink_neo_pixel task. This eliminates having to explicitly define a size of the data structure.
  • I was able to combine the new way of creating my collection of colors (line 26) with the C++ foreach loop (line 46) and clearly and simply iterate through the collection. You’ll note that I did not have to explicitly declare an iterator nor manipulate it anywhere in the foreach block. My only annoyance is syntax for how to reference each individual tuple element for the call to set the neopixel color (line 48).
  • I had to declare the app_main entry point as extern “C” in order for the linker to properly link with FreeRTOS.

The link to the older post is here: /2022/03/23/simple-programming-of-the-esp32-s3-devkitc-1-using-esp-idf/