ETLCPP / etl

Embedded Template Library
https://www.etlcpp.com
MIT License
2.14k stars 381 forks source link

Compilation fails when using etl::map with c++ < 17 #221

Closed labodj closed 4 years ago

labodj commented 4 years ago

Same problem of closed issue https://github.com/ETLCPP/etl/issues/210

Hello, I just noted that I'm having problem compiling my code when I use etl::map and c++ < 17.

I'm currently using platformio to compile my project with a custom GCC, I created a MCVE code that always spawn errors.

platformio.ini:

[env:megaatmega2560]
platform = atmelavr
board = megaatmega2560
framework = arduino
lib_deps = 
    https://github.com/labodj/avr_stl#c++17-fix
    Embedded Template Library
build_unflags = -std=gnu++11 -std=c++11
build_flags = -std=c++14

etl_profile.h:

#ifndef __ETL_PROFILE_H__
#define __ETL_PROFILE_H__

#define ETL_VERBOSE_ERRORS
#define ETL_CHECK_PUSH_POP
#define ETL_NO_STL
#define ETL_TARGET_DEVICE_GENERIC
#define ETL_TARGET_OS_NONE
#define ETL_COMPILER_GCC
#include "etl/profiles/auto.h"
#endif

main.cpp:

#include <Arduino.h>
#include <ArduinoSTL.h>
#include <etl/map.h>

etl::map<const char *, uint8_t, 10> testMap;

void setup()
{
}

void loop()
{
  testMap["hello"] = 9;
}

compiler used (gcc 9.3.0 with patch and fixes): https://blog.zakkemble.net/avr-gcc-builds/comment-page-1/#comment-209216

compilation output when compiled with c++11 or c++14 option:

Processing megaatmega2560 (platform: atmelavr; board: megaatmega2560; framework: arduino)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/megaatmega2560.html
PLATFORM: Atmel AVR 2.1.0 #97a1f01 > Arduino Mega or Mega 2560 ATmega2560 (Mega 2560)
HARDWARE: ATMEGA2560 16MHz, 8KB RAM, 248KB Flash
DEBUG: Current (simavr) On-board (simavr)
PACKAGES: 
 - framework-arduino-avr 5.0.0 
 - toolchain-atmelavr 1.50400.190710 (5.4.0)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 7 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <avr_stl> 1.2.2 #84a9878
|-- <Embedded Template Library> 18.1.1
|   |-- <avr_stl> 1.2.2 #84a9878
Building in release mode
Compiling .pio/build/megaatmega2560/src/main.cpp.o
Archiving .pio/build/megaatmega2560/libe01/libavr_stl.a
Indexing .pio/build/megaatmega2560/libe01/libavr_stl.a
Compiling .pio/build/megaatmega2560/FrameworkArduino/HardwareSerial3.cpp.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/IPAddress.cpp.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/PluggableUSB.cpp.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/Print.cpp.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/Stream.cpp.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/Tone.cpp.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/USBCore.cpp.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/WInterrupts.c.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/WMath.cpp.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/WString.cpp.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/abi.cpp.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/hooks.c.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/main.cpp.o
In file included from .pio/libdeps/megaatmega2560/avr_stl/src/memory:20,
                 from .pio/libdeps/megaatmega2560/avr_stl/src/char_traits:22,
                 from .pio/libdeps/megaatmega2560/avr_stl/src/iosfwd:21,
                 from .pio/libdeps/megaatmega2560/avr_stl/src/serstream:48,
                 from .pio/libdeps/megaatmega2560/avr_stl/src/ArduinoSTL.h:12,
                 from src/main.cpp:2:
.pio/libdeps/megaatmega2560/avr_stl/src/new:40:58: warning: dynamic exception specifications are deprecated in C++11 [-Wdeprecated]
Compiling .pio/build/megaatmega2560/FrameworkArduino/new.cpp.o
   40 |     _UCXXEXPORT void* operator new(std::size_t numBytes) throw(std::bad_alloc);
      |                                                          ^~~~~
.pio/libdeps/megaatmega2560/avr_stl/src/new:50:60: warning: dynamic exception specifications are deprecated in C++11 [-Wdeprecated]
   50 |     _UCXXEXPORT void* operator new[](std::size_t numBytes) throw(std::bad_alloc);
      |                                                            ^~~~~
Compiling .pio/build/megaatmega2560/FrameworkArduino/wiring.c.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/wiring_analog.c.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/wiring_digital.c.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/wiring_pulse.S.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/wiring_pulse.c.o
Compiling .pio/build/megaatmega2560/FrameworkArduino/wiring_shift.c.o
Archiving .pio/build/megaatmega2560/libFrameworkArduino.a
In file included from .pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/iterator.h:36,
                 from .pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/container.h:37,
                 from .pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/algorithm.h:44,
                 from .pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/map.h:40,
                 from src/main.cpp:3:
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/utility.h: In instantiation of 'constexpr etl::pair<T1, T2>::pair(etl::pair<U1, U2>&&) [with U1 = const char*&; U2 = unsigned char; T1 = const char*&; T2 = unsigned char]':
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/utility.h:238:65:   required from 'etl::pair<T1, T2> etl::make_pair(T1&&, T2&&) [with T1 = const char*&; T2 = unsigned char]'
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/map.h:925:49:   required from 'etl::imap<TKey, TMapped, TKeyCompare>::mapped_type& etl::imap<TKey, TMapped, TKeyCompare>::operator[](etl::imap<TKey, TMapped, TKeyCompare>::key_parameter_t) [with TKey = const char*; TMapped = unsigned char; TKeyCompare = etl::less<const char*>; etl::imap<TKey, TMapped, TKeyCompare>::mapped_type = unsigned char; etl::imap<TKey, TMapped, TKeyCompare>::key_parameter_t = const char*]'
src/main.cpp:13:18:   required from here
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/utility.h:159:39: error: cannot bind non-const lvalue reference of type 'const char*&' to an rvalue of type 'etl::remove_reference<const char*&>::type' {aka 'const char*'}
  159 |       , second(etl::move(other.second))
      |                                       ^
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/utility.h: In instantiation of 'constexpr etl::pair<T1, T2>::pair(etl::pair<U1, U2>&&) [with U1 = etl::imap<const char*, unsigned char, etl::less<const char*> >::iterator; U2 = bool&; T1 = etl::imap<const char*, unsigned char, etl::less<const char*> >::iterator; T2 = bool&]':
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/utility.h:238:65:   required from 'etl::pair<T1, T2> etl::make_pair(T1&&, T2&&) [with T1 = etl::imap<const char*, unsigned char, etl::less<const char*> >::iterator; T2 = bool&]'
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/map.h:1142:35:   required from 'etl::pair<etl::imap<TKey, TMapped, TKeyCompare>::iterator, bool> etl::imap<TKey, TMapped, TKeyCompare>::insert(etl::imap<TKey, TMapped, TKeyCompare>::rvalue_reference) [with TKey = const char*; TMapped = unsigned char; TKeyCompare = etl::less<const char*>; etl::imap<TKey, TMapped, TKeyCompare>::rvalue_reference = etl::pair<const char* const, unsigned char>&&; etl::imap<TKey, TMapped, TKeyCompare>::value_type = etl::pair<const char* const, unsigned char>]'
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/map.h:925:71:   required from 'etl::imap<TKey, TMapped, TKeyCompare>::mapped_type& etl::imap<TKey, TMapped, TKeyCompare>::operator[](etl::imap<TKey, TMapped, TKeyCompare>::key_parameter_t) [with TKey = const char*; TMapped = unsigned char; TKeyCompare = etl::less<const char*>; etl::imap<TKey, TMapped, TKeyCompare>::mapped_type = unsigned char; etl::imap<TKey, TMapped, TKeyCompare>::key_parameter_t = const char*]'
src/main.cpp:13:18:   required from here
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/utility.h:159:39: error: cannot bind non-const lvalue reference of type 'bool&' to an rvalue of type 'etl::remove_reference<bool&>::type' {aka 'bool'}
Indexing .pio/build/megaatmega2560/libFrameworkArduino.a
*** [.pio/build/megaatmega2560/src/main.cpp.o] Error 1

When it's compiled using c++17 option it runs just fine.

jwellbelove commented 4 years ago

Which release are you using?

labodj commented 4 years ago

I always use latest version I'm currently using Embedded Template Library: 18.1.1

jwellbelove commented 4 years ago

There may have been a mistake in platform.h with the definition of certain macros. Give me a few moments and I'll tag the latest push. (18.1.2)

labodj commented 4 years ago

No problem, I'm here to test :)

jwellbelove commented 4 years ago

OK, done.

labodj commented 4 years ago

Since the new version is not out on PlatforIO I just replaced 18.1.1 library with 18.1.2 you just released.

I noted 2 things:

This is the output with 18.1.2 and the same MCVE with c++14

Compiling .pio/build/megaatmega2560/src/main.cpp.o
In file included from .pio/libdeps/megaatmega2560/avr_stl/src/memory:20,
                 from .pio/libdeps/megaatmega2560/avr_stl/src/char_traits:22,
                 from .pio/libdeps/megaatmega2560/avr_stl/src/iosfwd:21,
                 from .pio/libdeps/megaatmega2560/avr_stl/src/serstream:48,
                 from .pio/libdeps/megaatmega2560/avr_stl/src/ArduinoSTL.h:12,
                 from src/main.cpp:2:
.pio/libdeps/megaatmega2560/avr_stl/src/new:40:58: warning: dynamic exception specifications are deprecated in C++11 [-Wdeprecated]
   40 |     _UCXXEXPORT void* operator new(std::size_t numBytes) throw(std::bad_alloc);
      |                                                          ^~~~~
.pio/libdeps/megaatmega2560/avr_stl/src/new:50:60: warning: dynamic exception specifications are deprecated in C++11 [-Wdeprecated]
   50 |     _UCXXEXPORT void* operator new[](std::size_t numBytes) throw(std::bad_alloc);
      |                                                            ^~~~~
In file included from .pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/iterator.h:36,
                 from .pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/container.h:37,
                 from .pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/algorithm.h:44,
                 from .pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/map.h:40,
                 from src/main.cpp:3:
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/utility.h: In instantiation of 'constexpr etl::pair<T1, T2>::pair(etl::pair<U1, U2>&&) [with U1 = const char*&; U2 = unsigned char; T1 = const char*&; T2 = unsigned char]':
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/utility.h:238:65:   required from 'etl::pair<T1, T2> etl::make_pair(T1&&, T2&&) [with T1 = const char*&; T2 = unsigned char]'
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/map.h:925:49:   required from 'etl::imap<TKey, TMapped, TKeyCompare>::mapped_type& etl::imap<TKey, TMapped, TKeyCompare>::operator[](etl::imap<TKey, TMapped, TKeyCompare>::key_parameter_t) [with TKey = const char*; TMapped = unsigned char; TKeyCompare = etl::less<const char*>; etl::imap<TKey, TMapped, TKeyCompare>::mapped_type = unsigned char; etl::imap<TKey, TMapped, TKeyCompare>::key_parameter_t = const char*]'
src/main.cpp:13:18:   required from here
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/utility.h:159:39: error: cannot bind non-const lvalue reference of type 'const char*&' to an rvalue of type 'etl::remove_reference<const char*&>::type' {aka 'const char*'}
  159 |       , second(etl::move(other.second))
      |                                       ^
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/utility.h: In instantiation of 'constexpr etl::pair<T1, T2>::pair(etl::pair<U1, U2>&&) [with U1 = etl::imap<const char*, unsigned char, etl::less<const char*> >::iterator; U2 = bool&; T1 = etl::imap<const char*, unsigned char, etl::less<const char*> >::iterator; T2 = bool&]':
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/utility.h:238:65:   required from 'etl::pair<T1, T2> etl::make_pair(T1&&, T2&&) [with T1 = etl::imap<const char*, unsigned char, etl::less<const char*> >::iterator; T2 = bool&]'
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/map.h:1142:35:   required from 'etl::pair<etl::imap<TKey, TMapped, TKeyCompare>::iterator, bool> etl::imap<TKey, TMapped, TKeyCompare>::insert(etl::imap<TKey, TMapped, TKeyCompare>::rvalue_reference) [with TKey = const char*; TMapped = unsigned char; TKeyCompare = etl::less<const char*>; etl::imap<TKey, TMapped, TKeyCompare>::rvalue_reference = etl::pair<const char* const, unsigned char>&&; etl::imap<TKey, TMapped, TKeyCompare>::value_type = etl::pair<const char* const, unsigned char>]'
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/map.h:925:71:   required from 'etl::imap<TKey, TMapped, TKeyCompare>::mapped_type& etl::imap<TKey, TMapped, TKeyCompare>::operator[](etl::imap<TKey, TMapped, TKeyCompare>::key_parameter_t) [with TKey = const char*; TMapped = unsigned char; TKeyCompare = etl::less<const char*>; etl::imap<TKey, TMapped, TKeyCompare>::mapped_type = unsigned char; etl::imap<TKey, TMapped, TKeyCompare>::key_parameter_t = const char*]'
src/main.cpp:13:18:   required from here
.pio/libdeps/megaatmega2560/Embedded Template Library_ID930/include/etl/utility.h:159:39: error: cannot bind non-const lvalue reference of type 'bool&' to an rvalue of type 'etl::remove_reference<bool&>::type' {aka 'bool'}
*** [.pio/build/megaatmega2560/src/main.cpp.o] Error 1
jwellbelove commented 4 years ago

Opps! My bad! I've been jumping back and forth between jobs today and forgot I hadn't merged to master yet. Sorry, I get that done now.

jwellbelove commented 4 years ago

Hopefully that's sorted it. (fingers crossed)

labodj commented 4 years ago

I've just tested it, the version is now correct but the error still appears. You solved it in the past in https://github.com/ETLCPP/etl/issues/210 That time I've tested it with c++17 only, today that I'm trying to manage to get my code back compatible with c++11 and c++14 the problem appears. I've tried to replace move with forward, but I'm not so c++ advanced, my random trial make only things worse.

jwellbelove commented 4 years ago

Are you saying one of the previous changes has been reversed?

labodj commented 4 years ago

No, i'm not. I'm saying that this problem has been fixed with 17.7.1 but at that time I've tested it compiling with c++17 option only, it doesn't work if compiled with c++14 or c++11 options.

I've just tested old 17.8.0 library version, with c++17 it's ok, with c++14 ot 11 it's not.

jwellbelove commented 4 years ago

Ok, I think I may I found the cause. C++17 seems to be better at deducing types for 'forward' as used in pair. Also it seems that there were a couple of more places where 'move' should have been replaced with 'forward' (I checked against another library's implementation) I've re-released 18.1.2

labodj commented 4 years ago

Ooooh yes!!! You nailed it! It now works as expected! Thanks a lot!

jwellbelove commented 4 years ago

Phew! I was getting worried there.