A problem with Streaming library

I noticed a strange problem with Streaming library mikalhart/Streaming@^1.0.0 on RPi2040. This snippet:

#include <Arduino.h>
#include <Streaming.h>
#include <iostream>
#include <chrono>

using namespace std;
using namespace std::chrono;

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
}

void loop()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);

  auto t0 = high_resolution_clock::now();
  delay(1000);
  auto t1 = high_resolution_clock::now();
  Serial << (t1-t0)/1us << endl;
}

compiles and runs fine on ESP32, but will not compile on RP2040, producing this error:

src/main.cpp:27:28: error: reference to 'endl' is ambiguous
   27 |   Serial << (t1-t0)/1us << endl;
      |                            ^~~~

The last line has to be replaced with:

  Serial << (t1-t0)/1us << "\n";

I’m not sure if I should discuss issues of this kind here, but I couldn’t find a github repo or another issues channel for this library.

end is ambiguous because both iostream defines it (via ostream) in the std:: namespace, which you import into the whole program by using using namespace std;, and the library defines it itself.

c:\users\max gerhardt\.platformio\packages\toolchain-gccarmnoneeabi@1.90201.191206\arm-none-eabi\include\c++\9.2.1\ostream:599:5: note: candidates are: 'template<class 
_CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::endl(std::basic_ostream<_CharT, _Traits>&)'
  599 |     endl(basic_ostream<_CharT, _Traits>& __os)
      |     ^~~~
In file included from src\main.cpp:2:
.pio\libdeps\pico\Streaming/Streaming.h:100:21: note:                 '_EndLineCode endl'
  100 | enum _EndLineCode { endl };
      |                     ^~~~

Doing

#include <Arduino.h>
#include <Streaming.h>
#include <iostream>
#include <chrono>

using namespace std::chrono;

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
}

void loop()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);

  auto t0 = high_resolution_clock::now();
  delay(1000);
  auto t1 = high_resolution_clock::now();
  Serial << (t1-t0)/1us << endl;
}

compiles fine and resolves end to the one defined in the libary.

You can still using using namespace std; when you refer to the library’s version of endl appropriately.

#include <Arduino.h>
#include <Streaming.h>
#include <iostream>
#include <chrono>

using namespace std;
using namespace std::chrono;

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
}

void loop()
{
  digitalWrite(LED_BUILTIN, HIGH);
  delay(500);
  digitalWrite(LED_BUILTIN, LOW);

  auto t0 = high_resolution_clock::now();
  delay(1000);
  auto t1 = high_resolution_clock::now();
  Serial << (t1-t0)/1us << _EndLineCode::endl;
}
1 Like

The question is why this error doesn’t occur when I compile it on ESP32 platform:

[env:esp32cam]
platform = espressif32
board = esp32cam
framework = arduino

Here is a bit shorter test version:

#include <Arduino.h>
#include <Streaming.h>
#include <chrono>

using namespace std;
using namespace std::chrono;

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  auto t0 = high_resolution_clock::now();
  delay(1000);
  auto t1 = high_resolution_clock::now();
  Serial << (t1-t0)/1us << endl;
}

Does the short example also fail when you #include <iostream> which might lead to the definition of endl?

1 Like

Of course, I missed that header. Thank you.