Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - Why is std::function<some_type_t, void> invalid?

In C++, if I try to do this:

std::function<void(bool,void)>

then the compiler will throw errors. Why is this? It's useful in many cases. One example:

//g++ -std=c++17 prblm.cpp
#include <cstdio>
#include <functional>

template<class type_t>
class some_callback
{
    public:
        using callback_t = std::function<void(bool,type_t)>;
        some_callback(callback_t _myfunc)
        {
            this->myfunc = _myfunc;
        }
        callback_t myfunc;
};

using callback_with_just_bool = some_callback<void>;
using callback_with_an_int_too = some_callback<int>;

int main()
{
    auto my_callback_with_int = callback_with_an_int_too([](bool x, int y)
    {
    }); //OK

    auto my_callback_just_bool = callback_with_just_bool([](bool x)
    {
    }); //Error

    auto my_callback_just_bool = callback_with_just_bool([](bool x,void z)
    {
    }); //Error
    return 0;
}

This allows for a very clean syntax if the user would like to optionally have additional data in their callback, but not have to. However, the compiler will reject code that tries to initialize an object of callback_with_just_bool

Why is it like this, and is there a clean way around it? Thanks.

Edit: The specific reason I'm trying to do this, in real world code, is in an event system. There is data provided to the event system about an individual object that wishes to conditionally receive events (e.x. "if you're close enough to the source, you'll receive a sound event") as well as data provided to a callback about the event (e.x. "a 10khz noise at X200 Y200"). Most of the time, the data needed to check the requirements will exist inside the data provided to the callback about the event, but I wanted to provided an optional additional data structure if that was not the case. Hence, the user would specify "void" if they didn't need this additional data structure.

like image 302
ai221 Avatar asked Nov 30 '22 14:11

ai221


1 Answers

"Why is this?"

Because the only permitted usage of void in a parameter list is to show that the function doesn't accept any parameters.

From [function]:

void

Indicates that the function takes no parameters, it is the exact synonym for an empty parameter list: int f(void); and int f(); declare the same function. Note that the type void (possibly cv-qualified) cannot be used in a parameter list otherwise: int f(void, int); and int f(const void); are errors (although derived types, such as void* can be used)

"Is there a clean way around it?"

I would suggest to specialize for void:

template<class type_t>
class some_callback
{
    std::function<void(bool,type_t)> myfunc;
};

template<>
class some_callback<void>
{
    std::function<void(bool)> myfunc;
};
like image 164
Edgar Rokjān Avatar answered Dec 04 '22 13:12

Edgar Rokjān