Skip to content

Commit 587eec5

Browse files
Add support for variadic Serial.print(...)
Allows combining multiple arguments into a single call to Print::print[ln], like Serial.print("Answer=", 66, HEX). This feature requires C++11 or newer to work, but if it is not available the old calls can still be used (the change has been wrapped in `#if __cplusplus >= 201103L ... #endif`). This change is backwards compatible: print(42, 16) prints "2A" as always, not "4216" (the latter can still be achieved with print(42, "", 16) ). This also works with multiple arguments: any numeric argument followed by an int will be treated as a (number, format) pair. The variadic function calls are inlined using an __attribute__ ((__always_inline__)), so they're equivalent to writing multiple sequential calls to print with one argument.
1 parent d2f7f1b commit 587eec5

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

Diff for: hardware/arduino/avr/cores/arduino/Print.h

+30
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,38 @@ class Print
7777

7878
size_t println(void);
7979

80+
#if __cplusplus >= 201103L
81+
template<typename ...Ts> _always_inline size_t println(const Ts &...args) { size_t t = print(args...); return t + println(); }
82+
#else
8083
template<typename T> _always_inline size_t println(const T &arg) { size_t t = print(arg); return t + println(); }
8184
template<typename T> _always_inline size_t println(const T &n, int f) { size_t t = print(n, f); return t + println(); }
85+
#endif // __cplusplus >= 201103L
86+
87+
88+
/** Variadic methods **/
89+
#if __cplusplus >= 201103L // requires C++11
90+
// Ensure there are at least two parameters to avoid infinite recursion.
91+
// e.g. `StringSumHelper s; print(s)` may be treated as `print(s, ...)`
92+
// with `...` being the empty list, thus calling `print(s)` again.
93+
// (This is because print(StringSumHelper) isn't explicitly defined.)
94+
template<typename T, typename T2, typename ...Ts>
95+
_always_inline size_t print(const T &arg, const T2 &arg2, const Ts &...args) {
96+
size_t t = print(arg);
97+
return t + print(arg2, args...);
98+
}
99+
// Some methods take an extra int parameter. If so, use these templates.
100+
// In a future, it would be nice to make the base/precision a special type.
101+
template<typename ...Ts> _always_inline size_t print( signed char n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
102+
template<typename ...Ts> _always_inline size_t print( signed short n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
103+
template<typename ...Ts> _always_inline size_t print( signed int n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
104+
template<typename ...Ts> _always_inline size_t print( signed long n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
105+
template<typename ...Ts> _always_inline size_t print(unsigned char n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
106+
template<typename ...Ts> _always_inline size_t print(unsigned short n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
107+
template<typename ...Ts> _always_inline size_t print(unsigned int n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
108+
template<typename ...Ts> _always_inline size_t print(unsigned long n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
109+
template<typename ...Ts> _always_inline size_t print( float n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
110+
template<typename ...Ts> _always_inline size_t print( double n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
111+
#endif // __cplusplus >= 201103L
82112
};
83113

84114
#undef _always_inline

Diff for: hardware/arduino/sam/cores/arduino/Print.h

+30
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,38 @@ class Print
7777

7878
size_t println(void);
7979

80+
#if __cplusplus >= 201103L
81+
template<typename ...Ts> _always_inline size_t println(const Ts &...args) { size_t t = print(args...); return t + println(); }
82+
#else
8083
template<typename T> _always_inline size_t println(const T &arg) { size_t t = print(arg); return t + println(); }
8184
template<typename T> _always_inline size_t println(const T &n, int f) { size_t t = print(n, f); return t + println(); }
85+
#endif // __cplusplus >= 201103L
86+
87+
88+
/** Variadic methods **/
89+
#if __cplusplus >= 201103L // requires C++11
90+
// Ensure there are at least two parameters to avoid infinite recursion.
91+
// e.g. `StringSumHelper s; print(s)` may be treated as `print(s, ...)`
92+
// with `...` being the empty list, thus calling `print(s)` again.
93+
// (This is because print(StringSumHelper) isn't explicitly defined.)
94+
template<typename T, typename T2, typename ...Ts>
95+
_always_inline size_t print(const T &arg, const T2 &arg2, const Ts &...args) {
96+
size_t t = print(arg);
97+
return t + print(arg2, args...);
98+
}
99+
// Some methods take an extra int parameter. If so, use these templates.
100+
// In a future, it would be nice to make the base/precision a special type.
101+
template<typename ...Ts> _always_inline size_t print( signed char n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
102+
template<typename ...Ts> _always_inline size_t print( signed short n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
103+
template<typename ...Ts> _always_inline size_t print( signed int n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
104+
template<typename ...Ts> _always_inline size_t print( signed long n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
105+
template<typename ...Ts> _always_inline size_t print(unsigned char n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
106+
template<typename ...Ts> _always_inline size_t print(unsigned short n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
107+
template<typename ...Ts> _always_inline size_t print(unsigned int n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
108+
template<typename ...Ts> _always_inline size_t print(unsigned long n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
109+
template<typename ...Ts> _always_inline size_t print( float n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
110+
template<typename ...Ts> _always_inline size_t print( double n, int f, const Ts &...args) { size_t t = print(n, f); return t + print(args...); }
111+
#endif // __cplusplus >= 201103L
82112
};
83113

84114
#undef _always_inline

0 commit comments

Comments
 (0)