Static function inside namepsace : compile on UNO not on DUE

Hi.

I,m working on a skech with a variadic data structure. I have 2 static function specialization getHelper, to get data out of the variadic.

I want to put those 2 static function into a namespace to limit there scope. It work well on UNO, but it did not compile on DUE:

error specialization of 'template<unsigned int idx, class T> struct InterfaceHelper::GetHelper' in different namespace

When outside a namespace, the two board compile...

tried couple of other board in the IDE list, the DUE seems to be the only one that not compiling...

Thanks.

template <typename T>
class InterfaceObj {
public:
	InterfaceObj(const char* key) : _key(key) {  };
	const char* _key;
	T value;
	InterfaceObj<T> operator=(T _value) { value = _value; };
	T operator()(){ return value;};
	char* getKey() const { return _key; };
};

namespace InterfaceHelper {
	template<size_t idx, typename T>
	struct GetHelper;

	//template<size_t idx, typename T>
	//struct SetHelper;
};

template<typename ... T>
struct Interface
{
};

template<typename T, typename ... Rest>
struct Interface<T, Rest ...>
{
    Interface(const InterfaceObj<T> first, const InterfaceObj<Rest> ... rest)
        : first(first)		//-&
        , rest(rest...)  //-
    {}
    
    InterfaceObj<T> first;	//-*
    Interface<Rest ... > rest; //-*

        
   template<size_t idx>
   auto get() -> decltype(InterfaceHelper::GetHelper<idx, Interface<T,Rest...>>::get(*this))
    {
        return InterfaceHelper::GetHelper<idx, Interface<T,Rest...>>::get(*this);
    }

    template<size_t idx>
    void set(T data)
     {
     	auto id = *(InterfaceHelper::GetHelper<idx, Interface<T,Rest...>>::get(*this));
     	id->_value = data;
     }

    template<size_t idx>
    auto getPtr() -> decltype(*InterfaceHelper::GetHelper<idx, Interface<T,Rest...>>::get(*this))
     {
     	return *InterfaceHelper::GetHelper<idx, Interface<T,Rest...>>::get(*this);
     }
};

template<typename T, typename ... Rest>
struct InterfaceHelper::GetHelper<0, Interface<T, Rest ... >> {
    static InterfaceObj<T> get(Interface<T, Rest...>& data) // <T>* --> <T> et & data
    {
        return data.first;
    }

};


template<size_t idx, typename T, typename ... Rest>
struct InterfaceHelper::GetHelper<idx, Interface<T, Rest ... >> {
    static auto get(Interface<T, Rest...>& data) -> decltype(GetHelper<idx-1, Interface<Rest ...>>::get(data.rest))
    {
        return GetHelper<idx-1, Interface<Rest ...>>::get(data.rest);
    }
};

I believe the reason is that the Arduino SAM Boards package of the Due is using a fairly old version of GCC. If you install Arduino SAMD Boards (which uses the same compiler version) and compile for one of those boards (e.g. Zero), or use Tools > Board > Boards Manager to roll Arduino AVR Boards back to version 1.6.11 and compile for one of those boards (e.g. Uno), you'll get the same error.

There is a newer version of the compiler, which is currently being used by the "Arduino SAMD Beta Boards", which is compatible with this code. If you're feeling adventurous, you can modify your Arduino SAM Boards installation to use this compiler version:

(In the Arduino IDE) Tools > Board > Boards Manager

Wait for the downloads to finish.

Scroll down through the available packages until you see "Arduino SAMD Beta Boards (32-bits ARM Cortex-M0+) by Arduino". Click on it.

Click "Install".

Wait for installation to finish.

Click "Close"

File > Preferences

Click the link at the line following File > Preferences > More preferences can be edited directly in the file. This will open the Arduino15 (or similar name depending on OS) folder.

Open packages/arduino/hardware/sam/1.6.11/platform.txt in a text editor.

Change line 20 from:

compiler.path={runtime.tools.arm-none-eabi-gcc.path}/bin/

to:

compiler.path={runtime.tools.arm-none-eabi-gcc-7-2017q4.path}/bin/

Change line 81 from:

recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group {compiler.combine.flags} {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -lm -gcc

to

recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -mcpu={build.mcu} -mthumb {compiler.c.elf.flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--start-group {compiler.combine.flags} {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group -lm

Save the file.

Restart the Arduino IDE.

Yes! it work like a charm !

Is it a risky trick to do to change the compiler like this ? If not, could it be change for good for the DUE ?

Taht make my code not portable, but at the end.. that work.

Thanks a lot.

Regards.

Nitrof

nitrof:
Is it a risky trick to do to change the compiler like this ?

It's risky in that the new compiler version hasn't been thoroughly tested. All users of the MKR Vidor 5000 board have been using this compiler version for over 6 months now and I haven't heard of any reports of problems. They also have beta testers using the same GCC version on the AVR for the last 3.5 months with no reported issues there. So the main concern would be that there hasn't been any testing at all of this compiler version with the Due's code.

Arduino tends to be pretty conservative about updating the compiler, since for the average Arduino user the most important thing is that they have an easy learning experience, rather than the best performance and the shiny new advanced C++ features. It's easy enough for a more advanced user like you to undo the change and go back to the old compiler version, but unleashing a problematic compiler on hundreds of thousands of beginners is a real disaster.

Another concern is the change I instructed you to make to line 81. I don't actually know what that -gcc flag I had you remove did. I only know that it's not supported in the newer compiler version. It would be best to do some research to find out why it was there and see if it needs to be replaced with some other flags. It might make sense to look at what the differences are between the Arduino SAM Boards platform.txt and the Arduino SAMD Beta Boards platform.txt (which you can find at packages/arduino/hardware/samd_beta/1.6.25/platform.txt).

If nothing else, it's kind of fun to mess around with the inner workings off the Arduino IDE a bit, and hopefully learn something along the way.

nitrof:
could it be change for good for the DUE ?

Yes, the 4.8.3 compiler version they're currently using is quite old and there are a lot of requests for Arduino to update it. We've been on avr-gcc 5.4.0 for a while now, though 5.4.0 actually has some bugs that are hopefully accelerating the update to 7.3.0. I suspect Arduino will update Arduino SAM Boards on the next release after they have done so for Arduino SAMD Boards. Unfortunately, development is not very active on Arduino SAM Boards so I don't know how long it would take them to do the next release.

nitrof:
Taht make my code not portable

Very good point!

nitrof:
Thanks a lot.

You're welcome. I'm glad if I was able to be of assistance. Enjoy!
Per

I don't actually know what that -gcc flag

I tried to find what it does, but did not. The doc I found are not made for dummies like me... lol. But in the process I find out that I was running 1.6.11 of DUE core and that there was a 1.6.12.

It still not compile with my code but, in the line 81, now the flag is set by default to -lgcc. And that work with the SAMD compiler without change. So that make only one line to change into the platform.txt to your solution to work.

If nothing else, it's kind of fun to mess around with the inner workings off the Arduino IDE a bit, and hopefully learn something along the way.

it did. compiler still come kind of magic to me... :stuck_out_tongue:

For now i'll keep thing this way and hope for an update of the core using the new compiler.
BTW, I tested another sketch I have that is also a bit bigger with this compiler and did not have any trouble...

regards.

Nitrof

nitrof:
It still not compile with my code but, in the line 81, now the flag is set by default to -lgcc. And that work with the SAMD compiler without change. So that make only one line to change into the platform.txt to your solution to work.

Good catch! I was using 1.6.11 also. They only recently released 1.6.12 and I hadn't noticed the change. I went through this same process a good while ago to help someone else who wanted to use a newer compiler version, so I was just going off of my memory of needing to delete -gcc.