Function that accepts different data types

I am writing a function that needs to accept different data types much like a standard print function i.e., serial.print().

serial.print() will accept “hello world” or 123456 or floating_point1. How can do i define my function to accept the same data types?

I think I need something like:

void myfunction(any parm1)

In the above what replaces “any” to accomplish my goal.

Thanks

How can do i define my function to accept the same data types?

print() is not a function. It is a method, of the Print class. Take a look at the Print class to see how it manages to have print() take so many kinds of arguments.

How can do i define my function to accept the same data types?

Create different functions, each with the same name, one for each data type.

Welcome to function overloading.

Or, if you want more generality, you can go the printf() route. and use stdarg.h.

You write a separate function for each data type. The functions have the same name (print), but accept different data types. It is called ooverloading a function. Which version of the function (overload) that is use is based on the signature of the function. The signature is the data type(s) passed to the function. Print("hi") and print(17178) are using different overloads, the sinatures are different (string and int) for instance.

You can get in trouble if the different types are the same length. word & pointers.

-jim lee

jimLee:
You can get in trouble if the different types are the same length. word & pointers.

-jim lee

?

jimLee:
You can get in trouble if the different types are the same length. word & pointers.

-jim lee

Not really. The compiler will know the type of every variable being passed into a function, so it will be able to select the right one if one is provided.

Thanks for all the input.

The function overload scheme sounds like something I might be able to do.

frank2644:
I am writing a function that needs to accept different data types much like a standard print function i.e., serial.print().

serial.print() will accept “hello world” or 123456 or floating_point1. How can do i define my function to accept the same data types?

I think I need something like:

void myfunction(any parm1)

In the above what replaces “any” to accomplish my goal.

Thanks

Here’s the code from my universal eeprom read/write functions. Notice how “T” is used to represent any data type.

// universal eeprom READ
template <class T> T eepromRead (const T *addr)
{
    uint8_t x;
    uint8_t *ptr;
    T value;

    x = sizeof (T);
    ptr = (uint8_t *)(void *)&value;

    while (x--) {
        *(ptr + x) = (eeprom_read_byte ((uint8_t *)(addr) + x));
    }

    return value;
}

// universal eeprom WRITE
template <class T> void eepromWrite (T *addr, T value)
{
    uint8_t x;
    uint8_t *ptr;

    x = sizeof (T);
    ptr = (uint8_t *)(void *)&value;

    while (x--) {
        eeprom_write_byte (((uint8_t *)(addr) + x), *(ptr + x));
    }
}

For example, if you try to write a “[b]uint16_t[/b]”, then the line “[b]x = sizeof (T)[/b]” will actually be compiled as “[b]x = sizeof (uint16_t):[/b]

Seeing how this code works, you should be able to figure out how to do it for your own use.

Hope this helps.

What Krupski just illustrated is called a function template, in case you would like to be able to look that up and get more information. It is similar to overloading a function except that the compiler generates all the overloaded functions for you based on what variable types you use in your code.

Templates only work if all of the code for the different types would be exactly the same in form, just with the different types substituted in.

Granted, overloading and templates aren’t mutually exclusive. Here is a sample set of functions I used for a desktop C++ program that can add variables of different types into an array of bytes for writing into a file. The first function adds a single object to the end of the binary array, the second adds an array of elements, and the 3rd adds the elements of an STL container to the byte array.

Don’t worry so much about the exact details of what functions I’m using here, just take it as an example of the way templates and overloading can be combined for maximum flexibility.

template<class T>
void append_raw(binary_t &v, const T &data, ENDIAN big_endian)
{
	for( size_t i=0; i<sizeof(T); i++ )
		v.push_back((char)((data>>(8*((bool)big_endian?(sizeof(T)-i-1):(i)))) & 0xFF));
}

template<class T> 
void append_raw(binary_t &v, const T* data, size_t n, ENDIAN big_endian)
{
	for( size_t i=0; i<n; i++ )
		append_raw(v, data[i], big_endian);
}

template<class Container>
void append_raw(binary_t &v, const Container &c, ENDIAN big_endian)
{
	for( typename Container::value_type i : c )
		append_raw( v, i, big_endian );
}

frank2644:
Thanks for all the input.

The function overload scheme sounds like something I might will be able to do.

think positive

Thanks again for all the suggestions. Unfortunately, I'm really new at Ardurino programming and many of the suggestions are over my head. I probably could figure it out, but my time is limited (I'm 75 years old :slight_smile: ).

Let me add one more bit of information: My function doesn't have to operate on the passed parameter, it will eventually just pass that parameter to a Print() method.

So is there a way for my function to pass through that parameter to a Print() method? Again given that parameter can be different types(char, float, etc)?

So is there a way for my function to pass through that parameter to a Print() method? Again given that parameter can be different types(char, float, etc)?

Function overloading still sounds like the easiest way to do what you want and is not complicated.

void setup()
{
  Serial.begin(115200);
  char aString[] = {"Wibble, Wobble"};
  aFunc("Hello World");
  aFunc(aString);
  aFunc('X');
  aFunc(123);
}

void loop()
{}

void aFunc(char inChar)
{
  Serial.print("Printing a char : ");
  Serial.println(inChar);
}

void aFunc(char * inChar)
{
  Serial.print("Printing a char * : ");
  Serial.println(inChar);
}

void aFunc(int inInt)
{
  Serial.print("Printing an int : ");
  Serial.println(inInt);
}

This program contains 3 different versions of the aFunc() function and automatically uses the appropriate version depending on the type of the parameter supplied.

If there is common code that needs to be run regardless of the data type that does not involve that data then put it in its own function and call it from each version of the function.

frank2644:
Thanks again for all the suggestions. Unfortunately, I’m really new at Ardurino programming and many of the suggestions are over my head. I probably could figure it out, but my time is limited (I’m 75 years old :slight_smile: ).

Let me add one more bit of information: My function doesn’t have to operate on the passed parameter, it will eventually just pass that parameter to a Print() method.

So is there a way for my function to pass through that parameter to a Print() method? Again given that parameter can be different types(char, float, etc)?

Details. What will it do before you “pass that parameter to a print() method”? It could just be as simple as doing this:

template<class T>
void whatever(T param)
{
  // Do whatever thing you want here.

  Serial.print(param);
}

If you keep asking an abstract, generic question you will keep getting abstract, generic answers. You have already been told the two ways that this problem can be tackled: overloading and templates. We’ve even given examples. The proper way to apply these tools will depend on the details of how you want this function to operate. So spill the beans.

Thank you Jiggy-Ninja.

That sounds like exactly what I need.

Frank

Oops, sorry Jiggy, I was so happy with your reply that I overlooked your request that I "spill the beans".

Basically, I am trying to write a function to scroll a 16x2 LCD so that the last message is on the bottom line and the previous message is on the top line. As new messages come in this function will automatically bump up the prior message and print the new message on the bottom line.

So this new function will send commands to the LCD to scroll it and then pass the latest message through to be displayed.

There is a couple of ways to decide if scrolling is necessary the simplest might be to have two functions one if the calling code wants to scroll and another for no scrolling.. Kinda mirroring the print() and println() facilities.

One more bean: I'm actually using a Nodemcu, not an Arduino. The Nodemcu is compatible to an Arduino and uses the same development platform.

Again, thank you.

Frank

P.S. I pasted your code into the Arduino "Blink" example program and it gave me compile errors no matter where I put the code (setup, loop, etc) Obviously I don't really know what I am doing. I'm still trying and I may have some more questions later.

I pasted your code into the Arduino "Blink" example program and it gave me compile errors no matter where I put the code

Post what you tried here so that er can see what you did.

I pasted the code posted by Iggy into the bottom of my program and also into an Arduino example “blink”. In both cases I get these errors:

Blink.ino:21:15: error: variable or field ‘whatever’ declared void
Blink.ino:21:15: error: ‘T’ was not declared in this scope

Here is the complete Blink code, any suggestions are appreciated:
void setup() {
// initialize digital pin 13 as an output.
pinMode(13, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}

template
void whatever(T param)
{
// Do whatever thing you want here.

Serial.print(param);
}