Curious why this code won't compile in version 1.6.5 but does in 1.6.6 and 1.6.7

As I've mentioned earlier I'm new to the Arduino ecosphere so please bear with me. I'm working with the new Simblee bluetooth devices and according to their documentation one is supposed to use the 1.6.5 R5 version IDE. I am clueless as to why one can't use the latest version.

Anyway I'm trying to concatenate a message string to send via I2C and my test code won't compile in version 1.6.5 but does in 1.6.6 on up.

Here's my test code:

#include <Wire.h>
const int ledPin =  13;
int ledState = LOW; 

int red = 255;
int green = 50;
int blue = 0;

String str;
char message[14];

void setup() {

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, ledState);
  Wire.begin();         // join i2c bus (address optional for master)
  Serial.begin(9600);   // start serial for output
}

void loop() {
  
  create_message();
  
  Wire.beginTransmission(8); // transmit to device #8
  Wire.write(message);       // sends five bytes
  Wire.endTransmission();    // stop transmitting
  
  delay(500);
}

void create_message() {

  str = red;
  str.concat(",");
  str.concat(green);
  str.concat(",");
  str.concat(blue);
  str.toCharArray(message, 14);

  Serial.println(str);
}

Here is the error message:

Arduino: 1.6.5 (Windows 8.1), Board: "Arduino/Genuino Uno"

Build options changed, rebuilding all

Using library Wire in folder: C:\arduino-1.6.5-r5\hardware\arduino\avr\libraries\Wire

C:\arduino-1.6.5-r5\hardware\tools\avr/bin/avr-g++ -c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10605 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -IC:\arduino-1.6.5-r5\hardware\arduino\avr\cores\arduino -IC:\arduino-1.6.5-r5\hardware\arduino\avr\variants\standard -IC:\arduino-1.6.5-r5\hardware\arduino\avr\libraries\Wire C:\Users\Don\AppData\Local\Temp\build4751821725965981877.tmp\master_writer_Don.cpp -o C:\Users\Don\AppData\Local\Temp\build4751821725965981877.tmp\master_writer_Don.cpp.o

master_writer_Don.ino: In function 'void create_message()':
master_writer_Don.ino:34:7: error: ambiguous overload for 'operator=' (operand types are 'String' and 'int')
master_writer_Don.ino:34:7: note: candidates are:
In file included from C:\arduino-1.6.5-r5\hardware\arduino\avr\cores\arduino/Print.h:26:0,
from C:\arduino-1.6.5-r5\hardware\arduino\avr\cores\arduino/Stream.h:26,
from C:\arduino-1.6.5-r5\hardware\arduino\avr\libraries\Wire/Wire.h:26,
from master_writer_Don.ino:1:
C:\arduino-1.6.5-r5\hardware\arduino\avr\cores\arduino/WString.h:86:11: note: String& String::operator=(const String&)
String & operator = (const String &rhs);
^
C:\arduino-1.6.5-r5\hardware\arduino\avr\cores\arduino/WString.h:86:11: note: no known conversion for argument 1 from 'int' to 'const String&'
C:\arduino-1.6.5-r5\hardware\arduino\avr\cores\arduino/WString.h:87:11: note: String& String::operator=(const char*)
String & operator = (const char cstr);
^
C:\arduino-1.6.5-r5\hardware\arduino\avr\cores\arduino/WString.h:87:11: note: no known conversion for argument 1 from 'int' to 'const char
'
C:\arduino-1.6.5-r5\hardware\arduino\avr\cores\arduino/WString.h:88:11: note: String& String::operator=(const __FlashStringHelper*)
String & operator = (const __FlashStringHelper str);
^
C:\arduino-1.6.5-r5\hardware\arduino\avr\cores\arduino/WString.h:88:11: note: no known conversion for argument 1 from 'int' to 'const __FlashStringHelper
'
ambiguous overload for 'operator=' (operand types are 'String' and 'int')

I see it mentions Windows 8.1 when I'm actually using Windows 10...

Delta_G:

str = red;
str = String(red);

Thanks Delta_G. Seems rather simple. But the bigger question is why does the later versions not complain about it?

donmerch:
Thanks Delta_G. Seems rather simple. But the bigger question is why does the later versions not complain about it?

Sometimes newer code overloads assignments and constructors, thus supporting type mis-matches that otherwise were not supported.

Delta_G:
The thing about versions is that sometimes the code changes between them. Check out the String class in both versions and see if there is a difference.

Where do I look to find the class listing?

Ok thanks. I'll have a look.

Its not so much newer code, its the fact that IDE 1.6.6 enabled C++11.

This code has been here for a long time. Its just every IDE below 1.6.6 can only compile C++98 by default.
https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/WString.h#L89-L92

These lines work due to the C++ one time conversion rule. In any expression the compiler will automatically apply an implicit conversion to any compatible type (Input can be implicitly converted to StringSumHelper which the String class accepts).

With out the C++11 extras enabled, the compiler can use the constructor to do the conversion (create a temporary String object) and use the assignment operator which accepts a String. However this cannot be done in this case as the constructors are marked 'explicit' meaning it cannot implicitly use them (you have to explicitly cast it like in Delta_G's code).

I must have missed the announcement that the IDE has moved to a different version of C++. It seems odd that it did that between "minor" releases (1.6.5 to 1.6.5).

It is only a minor change. C++ did not add any breaking changes between C++98 and C++11, only new features.

Minor change? According to Wikipedia:

Areas of the core language that were significantly improved include multithreading support, generic programming support, uniform initialization, and performance. Significant changes were also made to the C++ Standard Library, incorporating most of the C++ Technical Report 1 (TR1) libraries, except the library of mathematical special functions

The word "significant" appears there more than once.

No matter, regardless of how you want to label it, the changes still don't break things, there have only been additions. And in reality C++11 has been usable if needed since 1.5.7, a minor tweak in the IDE is what made it default.

And more relevant is the fact versions reflect the actual IDE, not one particular core available for use with the IDE (The AVR core did upgrade from 1.5.x to 1.6.x). There are many cores and many different compilers. Basically the IDE is usable with more than one architecture/compiler (Due & Zero for example ).

Essentially the cores get updated and released independently of the IDE and each other (especially third party ones like Teensy, ESP8266, etc...). They also have their own versions. You can install, remove, and update them all through the board manager.

Areas of the core language that were significantly improved include multithreading support, generic programming support, uniform initialization, and performance.

So arduino can support multiple threads now?

Thomas499:
So arduino can support multiple threads now?

No, many features are not included in the avr-gcc implementation of C++11. A short list is as follows:

  • C++ Stl library.
  • Exception handling.
  • Multi threading support (not available on any CPU with only a single core/processor).
  • Garbage collection.
  • World domination library.

Thomas499:
So arduino can support multiple threads now?

The hardware doesn't support it so, no.

World domination library.

We all miss that one. :slight_smile:

No, many features are not included in the avr-gcc implementation of C++11. A short list is as follows:

C++ Stl library.

Exception handling.

Multi threading support (not available on any CPU with only a single core/processor).

Garbage collection.

World domination library.

So if i had a dual processor I could run 2 threads, and if I had a tri-processor I could run 3 threads?

If I use an external editor, would that bypass the avr-gcc limitations? If I get an arduino yun shield will that upgrade it to a multi core processor?

They are still separate processors. You can write program for each processor and distribute tasks between them (parallel processing).

The AR9331 only has a single core, but gcc for its linux OS will have support for multiple threads of execution, however the kernel will simply use interrupts to switch between a single thread at a time. You can replicate the functionality on an Arduino (Uno, Due, etc..), there is just no thread library provided in C++ to do the task switching for you (many implementations you can use however, even an OS like NilRtos or ChibiOS).

Search the forums for multi threading, it has been asked a zillion times.