How to use C++ like modules in Arduino

Hello everyone, I recently came across this thread on How to use modules in C++ posted on the forum by @
frek
dated June 7, 2022.

Please, I have two broad questions:
1.) Does anyone know if Arduino or Raspberry Pi supports import functionality i.e. what would it require to implement something like this in Arduino: import std;

2.) Also, what are the benefits (if any) to gradually transitioning from header files (.h) to importing module files (.cppm) especially in regards to IoT development? Are there advantages to using the latter in terms of code maintainability and manageability? I guess I mean: is it worth the effort going forward?

Thank you all.
!)
There is a difference between Arduino and Raspberry PI.
Arduino is more limited [regarding C++] than Raspberry PI. See:

https://forum.arduino.cc/t/which-version-of-c-is-currently-supported/1285868/5

for a discussion about C++ and the version.

With Raspberry PI you have a nearly full fledged Linux system so that you may install the latest compiler.

2)
Using import over #include means getting rid of the preprocessor and it's sometimes surprising effects.
So it's good to do this but not at any cost...
Well noted. Thank you for your response.

Addendum: Someone from another platform also mentioned that the import feature may not be applicable to current Adruino compilers since they use C++11, C++14 and C++17 standards while the former is found in C++20. Any thoughts?
Using import over #include means getting rid of the preprocessor

Using modules doesn't get rid of the preprocessor, their use simply changes how the preprocessor does its work.

https://andreasfertig.blog/2021/09/cpp20-modules-the-possible-speedup/

With modules there are module interface files, similar to header files, and internal partition files.

The source file where main( ) resides is normally classified as an interface file when doing imports. At least with Visual Studio.

It sounds more complicated than it is in actual usage, though how to craft your own module code is somewhat different than writing non-module header/source files. Not "a whole new language" different, though.

One of the main advantages of modules is the speed of compiling after the initial first time needed to parse and compile the module code. As long as module code is unchanged the compiler doesn't need to recompile the module.

Think precompiled headers, the C++ stdlib libraries only need to be compiled once with each project. User created modules might if the code within the file(s) changes.

If the Arduino compilers aren't at least C++20 compliant then importing modules won't work. Even main-stream compilers other than MSVC currently have only partial support for modules (as well as a handful of other features).

https://en.cppreference.com/w/cpp/compiler_support/20

C++23 modified the module importation scheme so now to use the C++ stdlib you can import std; or import std.compat;.

https://open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2465r1.pdf

Before C++23 was finalized MS had their own version, import std.core;, but it was buggy as all get out.

I have a few very rudimentary examples repo'd on using modules. Pre-C++20, C++20 and C++23.

Rude, crude and lewd, but it lets someone get the basic idea of modules. Along with formatting output available starting with C++20.

https://github.com/GeorgePimpleton/module_testing

+-----+

FYI, if you like the C++ formatting options but want/need to avoid C++20/23 there's the {fmt} library that requires only C++11. A minimal subset of C++11.

https://fmt.dev/latest/
@GeorgePlusPlus
Awesome! Thanks for the clarification. I guess I'd stick to what's obtainable for now in terms of C++11 standard support for Arduino.

As per libraries, what are your thoughts on using third-party vector container libraries in Adruino, since native std::vector and std::array type containers appear not to be supported? I saw one of such third party libraries which the author claimed could function like (but slightly different from) native std::vector<T> library. However, from your personal experience, could this pose potential drawbacks in the future? Thank you in advance
Last edited on
I don't 'do' Arduino in any way, shape or form, so I can't really make informed comments. I'm a full-throated Windows Desktop kinda programming hobbyist. Been doing this hobby before 1998.

I do know the Arduino implemented C++ is very much non-standard, being a restrictive subset with a few modifications thrown in to work on the hardware. Aren't the chips onboard running at 10-20 MHz with around 2KB of memory? There are definite tradeoffs with hardware using programmable embedded software.

With that said and out of the way.....

When it comes to an intentionally limited support compiler like Arduino I'd personally avoid 3rd party libraries. The C++ subset available is likely because of hardware constraints such as available memory. Only compilers that support (or will eventually support) the full C++ standard, whatever the version, would I bother trying to shove a 3rd party library into the mix.

And then I'd use a package manager to do the grunt work of getting and maintaining any used library. I personally use vcpkg.

https://vcpkg.io/en/index.html

Any installed library is integrated into my Visual Studio 2022 IDE, though if I wanted to do CMake command-line compiling vcpkg works as well.

I guess I'd stick to what's obtainable for now in terms of C++11 standard support for Arduino.
There might be some C++14/C++17 features available in the Arduino compiler you should investigate. Even if only a cursory look. I honestly don't know if the available compiler isn't C++11 only capable.

M'ok, the Arduino compiler is artificially restricted to C++11, and a rather small subset of C++11 at that. GNU based. There is no C++14/17/20/23 support, and likely never will. (Though, never say never)

I can't rattle off the top of my head what even for a fully compliant compiler most of what what C++11/14/17/20/23 offers to the C++ toolbox, though I doubt one C++17 feature, <filesystem>, would be of any use for Arduino.



Last edited on
I recently came across this thread

FYI, you can post a link to the thread so everyone doesn't have to search for it.

https://cplusplus.com/forum/general/283863/

Looking at the entirety of the thread and the problems I can see are VS 2019 related for the most part.

VS can get rather snotty about that. VS 2019 was especially peevish and contrary.

The file extensions now in 2024 aren't such a critical deal with VS 2022.

My understanding of how to make custom modules work has also increased since 2022.

I made a couple of modifications to frek's original code, adding some output statements to augment using the custom module, and lo! The danged stuff works!

vector.cpp (defaulted to /interface, as it should be):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
export module Vector;

export class Vector
{
public:
   Vector( int s );

   double& operator[]( int i );
   int     size( );

private:
   double* elem; // elem points to an array of sz doubles
   int     sz;
};

Vector::Vector( int s )
   : elem { new double[s] }, sz { s } // initialize members
{ }

double& Vector::operator[]( int i ) { return elem[i]; }
int     Vector::size( )             { return sz; }

export int size( Vector& v ) { return v.size( ); }


main.cpp (/interface default, as it should be):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Vector;

import <iostream>;

int main( )
{
   std::cout << "Hello, C++20 modules!\n";

   Vector vec( 1 );

   vec[0] = 5;

   std::cout << vec[0] << '\n';

   std::cout << std::format( "The size of the Vector is {}\n", vec.size( ) );

   std::cout << std::format( "The size of the Vector is {}\n", size( vec ) );
}

Hello, C++20 modules!
5
The size of the Vector is 1
The size of the Vector is 1

frek's original code is compilable in VS 2022 with one minor change:
export int size(const Vector& v) { return v.size(); }
needs the const removed. That is it!

Does this help you with working with the Arduino compiler? Not one damned bit, but it sure was fun revisiting that topic. :Þ
@GoergePlusPlus

Nice! And yes, it helps a lot!
There might be some C++14/C++17 features available in the Arduino compiler you should investigate

Indeed, I think current Arduino complier does support standard C++14 and C++17. And thank you for the detailed comments and resources.
Last edited on
To use C++23 features with my modified frek code you only need to change main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import Vector;

import std;

int main( )
{
   std::cout << "Hello, C++23 modules!\n";

   Vector vec( 1 );

   vec[0] = 5;

   std::cout << vec[0] << '\n';

   std::print( "The size of the Vector is {}\n", vec.size( ) );

   std::println( "The size of the Vector is {}", size( vec ) );
}
I think current Arduino complier does support standard C++14 and C++17.

I'm not even remotely knowledgeable about what the Arduino compiler can and can't do. I have more than enough to keep me busy with VS 2022 to play about with. Every day the more I learn about C++ the more I discover I don't know all that much.

Modules I do have more than nary a clue about.

*Skål!*
Registered users can post here. Sign in or register to post.