WiFiClient client;
const uint8_t* buf = ...;
size_t size = ...;
Print *p = &Serial;
p->write(buf, size);
p = &client;
p->write(buf, size);
It is also possible to do the same with function objects, without relying on the fact that HardwareSerial and WiFiClient are derived from Print.
This version will work for any other class which has write method with the same arguments and return type:
#include <functional>
//...
std::function<size_t(const uint8_t*, size_t)> writeFunc;
writeFunc = std::bind(static_cast<size_t (HardwareSerial::*)(const uint8_t*, size_t)>(&HardwareSerial::write), Serial, std::placeholders::_1, std::placeholders::_2);
writeFunc(buf, sizeof(buf));
writeFunc = std::bind(static_cast<size_t (WiFiClient::*)(const uint8_t*, size_t)>(&WiFiClient::write), client, std::placeholders::_1, std::placeholders::_2);
writeFunc(buf, sizeof(buf));
Note that we have to do a static_cast on the first argument of std::bind. This is because write is an overloaded member function, so we need to tell the compiler which overload we want to use. For non-overloaded functions, you don't need to do the static_cast.
This code is undeniably ugly, so you might want to make it slightly more readable by using lambdas:
std::function<size_t(const uint8_t*, size_t)> writeFunc;
writeFunc = [](const uint8_t* b, size_t s) -> size_t {
return Serial.write(b, s);
};
writeFunc(buf, size);
writeFunc = [&client](const uint8_t* b, size_t s) -> size_t {
return client.write(b, s);
};
writeFunc(buf, size);
Again, this may be used for any class with size_t write(const uint8_t*, size_t) member function.
One word of warning: lambdas in C++ are not closures, i.e. they do not extend the lifetime of captured variables. In the example above client is passed into lambda by reference, and you need to make sure that client object will actually exist at the point when you call writeFunc.