Carlos Bello
Carlos Bello

Reputation: 262

Pointers to undefined functions and parameters in C ++

I have the following code:

#include<iostream>
using namespace std;

void saludo();
void despedida();

int main(){
    void (*Ptr_Funciones[2])() = {saludo, despedida};
    (Ptr_Funciones[0])();
    (Ptr_Funciones[1])();

    return 0;
}

void saludo(){
    cout<<"\nHola mundo";
}

void despedida(){
    cout<<"\nAdios mundo"<<endl<<endl;
}

Based on this, a few questions were generated which I investigated before asking but did not fully understand.

The questions are:

  1. How do I make an array of functions, if they are of a different type?

  2. I know that in C ++ this notation is used for undetermined parameters: (type var ...) The thing is, I don't know how to interact with them inside the function.

  3. If questions 1 and 2 are possible, can these points be combined when creating function arrays?

I really have investigated. But I can't find much information, and the little I did find I didn't understand very well. I hope you can collaborate with me.

Thank you very much.

Upvotes: 3

Views: 98

Answers (3)

sehe
sehe

Reputation: 393593

Use a type alias to make things readable:

Live On Coliru

using Signature = void();
Signature* Ptr_Funciones[] = { saludo, despedida };

Prints

Hola mundo
Adios mundo

More flexible:

You can also use a vector:

Live On Coliru

#include <iostream>
#include <vector>
using namespace std;

void saludo() { cout << "\nHola mundo"; }
void despedida() { cout << "\nAdios mundo" << endl << endl; }

int main() {
    vector Ptr_Funciones = { saludo, despedida };

    Ptr_Funciones.front()();
    Ptr_Funciones.back()();
}

Prints the same.

More Flexibility: Calleables of Different Types

To bind different types of functions, type-erasure should be used. std::function helps:

Live On Coliru

#include <iostream>
#include <functional>
#include <vector>
using namespace std;

void saludo(int value) { cout << "\nHola mundo (" << value << ")"; }
std::string despedida() { cout << "\nAdios mundo" << endl << endl; return "done"; }

int main() {
    vector<function<void()>>
        Ptr_Funciones {
            bind(saludo, 42),
            despedida
        };

    Ptr_Funciones.front()();
    Ptr_Funciones.back()();
}

Prints

Hola mundo (42)
Adios mundo

Upvotes: 2

aspen100
aspen100

Reputation: 965

How do I make an array of functions, if they are of a different type?

You can, but you don't want to. It doesn't make semantic sense. An array is a collection of the same kind of thing. If you find that you need to make a collection of different kinds of things, there are several data structures at your disposal.

I know that in C++ this notation is used for undetermined parameters: (type var ...) The thing is, I don't know how to interact with them inside the function.

Here's how you can use the syntax you mention. They're called variadic functions.

If questions 1 and 2 are possible, can these points be combined when creating function arrays?

Erm, I can't imagine why/when a combination of these two would be needed, but out of intellectual curiosity, awayyy we go...

A modified version of the code from the reference link above that kinda does what you want (i've used a map instead of an array, cuz why not):

#include <iostream>
#include <cstdarg>
#include <unordered_map>

template<typename T>
using fooptr = void (*) (T *t...);

struct A {
    const char *fmt;
    
    A(const char *s) :fmt{s} {}
};

struct B : public A {

    B(const char *s) : A{s} {}
};

void simple_printf(A *a...)
{
    va_list args;
    auto fmt = a->fmt;
    va_start(args, a);
 
    while (*fmt != '\0') {
        if (*fmt == 'd') {
            int i = va_arg(args, int);
            std::cout << i << '\n';
        } else if (*fmt == 'c') {
            // note automatic conversion to integral type
            int c = va_arg(args, int);
            std::cout << static_cast<char>(c) << '\n';
        } else if (*fmt == 'f') {
            double d = va_arg(args, double);
            std::cout << d << '\n';
        }
        ++fmt;
    }
 
    va_end(args);
}
 

int main()
{
    A a{"dcff"};
    B b{"dcfff"};

    std::unordered_map<size_t, fooptr<struct A>> index;
    index[1] = simple_printf;
    index[5] = simple_printf;
    
    index[1](&a, 3, 'a', 1.999, 42.5);
    index[5](&b, 4, 'b', 2.999, 52.5, 100.5);
}

This still really doesn't do what you wanted (i.e., give us the ability to choose from different functions during runtime). Bonus points if you understand why that's the case and/or how to fix it to do what you want.

Upvotes: 2

GuidedHacking
GuidedHacking

Reputation: 3923

Here is one solution that is possible, whether it fits your needs I'm not sure.

#include <Windows.h>
#include <iostream>

void saludo()
{
    std::cout << "\nHola mundo"  << std::endl;;
}

void despedida()
{
    std::cout << "\nAdios mundo"  << std::endl;
}

void* fnPtrs[2];

typedef void* (VoidFunc)();

int main()
{
    fnPtrs[0] = saludo;
    fnPtrs[1] = despedida;

    ((VoidFunc*)fnPtrs[0])();
    ((VoidFunc*)fnPtrs[1])();

    std::getchar();

    return 0;
}

Upvotes: -1

Related Questions