Is it possible to reserve function reference into unordered_map or vector?

185 views Asked by At

i am making some callback system and i wonder if i can reserve function reference to unordered_map so that i can invoke it later.

float func_imp(float x)
{
    return x;
}
int main()
{
    using Tumap = unordered_map<int, float(&)(float)>;
    Tumap umap;
    umap.emplace(0, func_imp);
    (umap[0])(10.1); //a reference type cannot be value-initialized

    using Tvec = vector<float(&)(float)>;
    Tvec uvec; // pointer to reference is illegal
    //uvec.emplace_back(func_imp);
}

Is it possible to use this type of containers to reserve callback functions? if not, is it the only way to use function pointer?

2

There are 2 answers

1
AudioBubble On BEST ANSWER

Regardless of wether this is something you should be doing or not (the comments under your question are covering this already), it's still worth answering your question as is.

The [] operator of map types is a veritable swiss army knife. You can do a lot of things with it.

  • You can assign a value.
  • You can lookup the value.
  • You can lookup a value even if it doesn't exist yet.

Because of this, using that operator imposes some requirements for whatever type is stored in the map. In this specific case, you are running into the requirement that it has to be value-initializable, which references cannot be.

This applies to regular references as well by the way, not just function references.

So the answer is: You can store references in a map as much as you like as long as you don't use any function of the map that requires the reference to do something it's not allowed to.

In this case, you can use umap.at(0)(10.1);. One of the big differences between [] and at() is that if the key is not set yet, at() will throw an exception instead of creating a value-initialized value.

1
eerorika On

Is it possible to use this type of containers to ...

Regardless of how this sentence continues: No, it is not possible to use this type of containers. Specifically, element type of no standard container can be a reference. Reference types do not satisfy the requirements that containers have for their element type (at least not when using the standard allocator).

if not, is it the only way to use function pointer?

No, function pointer is not the only way, but it is a way that works.

Other alternatives are function objects such as an erasing function wrapper such as std::function, or a reference wrapper such as std::reference_wrapper.

i just thought there is no need to make dereference.

If you mean syntactically, then I have good news that make your concern irrelevant: There is no need to explicitly indirect through a pointer to function. The indirection is implicit just like with function references. Their call syntax is identical Example:

float(&ref)(float) = func_imp;
float(*ptr)(float) = func_imp;
ref(42.);
ptr(42.);

As such, you needen't worry.

If you are talking about having to indirect through the pointer at runtime at the cost of performance, I have bad news that make your concern irrelevant: References are also a form of indirection just as much as pointers are. They are (typically) not an optimisation.