The INLINE test in the source tree, tests/inline/, is also the example of header-only modules.
Two INLINE modules
# INLINE: header only; several languages (the shared locale matcher), a
# format, every artefact that has a definition.
$MODULE alpha INLINE
$NAMESPACE inl
$INCLUDE <iomanip>
$LANGUAGE en
$STRING ENABLE
$STREAMABLE ENABLE
$THROW ENABLE
$EXCEPTION INHERITED std::exception
$MESSAGE Alpha
@ n int
"alpha {$n;std::setw(3);fill('0')}"
[C.utf8]
"alpha C.utf8 {$n}"
# A second INLINE module in the same translation unit: its helpers must not
# collide with alpha's.
$MODULE beta INLINE
$NAMESPACE inl
$LANGUAGE en
$STRING ENABLE
$SYSLOG ENABLE
$MESSAGE Beta
@ who std::string const &
"beta {$who}"
[C.utf8]
"beta C.utf8 {$who}"
and an ordinary one:
# An ordinary module (source file) next to the INLINE ones.
$MODULE gamma
$NAMESPACE inl
$LANGUAGE en
$STRING ENABLE
$MESSAGE Gamma
@ n long
"gamma {$n}"
[C.utf8]
"gamma C.utf8 {$n}"
alpha.hh and beta.hh hold every definition; there is no alpha.cpp. Both need the locale matcher and the value appender; they share one copy through namespace mstring_detail_v1, whose blocks are include-guarded. gamma.cpp keeps its own in an unnamed mstring_local_v1, so the three coexist.
Two translation units
// A second translation unit including the INLINE headers: the definitions
// must link without duplicates.
#include "alpha.hh"
#include "beta.hh"
std::string Other( )
{
return inl::AlphaStr( 5 ) + " / " + inl::BetaStr( "other" );
}
#include "alpha.hh"
#include "beta.hh"
#include "gamma.hh"
#include <iostream>
#include <locale>
std::string Other( );
int main( )
{
std::locale const utf8( "C.utf8" );
std::cout << inl::AlphaStr( 7 ) << '\n'
<< inl::AlphaStr( 7, utf8 ) << '\n'
<< inl::AlphaStreamable( 8 ) << '\n'
<< inl::BetaStr( "ada", utf8 ) << '\n'
<< inl::GammaStr( 9L, utf8 ) << '\n'
<< Other( ) << '\n';
try
{
inl::ThrowAlpha( 1 );
}
catch ( std::exception const &e )
{
std::cout << e.what( ) << '\n';
}
}
Both main.cpp and other.cpp include alpha.hh and beta.hh: the inline definitions link once.
alpha 007
alpha C.utf8 7
alpha 008
beta C.utf8 ada
gamma C.utf8 9
alpha 005 / beta other
alpha 001
CMake
mstring_generate(GEN alpha.msg INLINE)
mstring_generate(GEN beta.msg INLINE)
mstring_generate(GEN gamma.msg)
add_executable(app main.cpp other.cpp ${GEN})
INLINE tells mstring_generate() not to wait for a source file.
What a call costs
From bench/ (gcc 11, -O2): a two-parameter string function 94 ns, a constant text 40 ns, a five-language message 134 ns — see Performance.

