C ++ - Почему std :: functionнедействительным? - PullRequest
0 голосов
/ 23 ноября 2018

В C ++, если я попытаюсь сделать это:

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

, компилятор выдаст ошибки.Почему это?Это полезно во многих случаях.Один пример:

//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;
}

Это позволяет использовать очень чистый синтаксис, если пользователь желает иметь дополнительные данные в своем обратном вызове, но не обязан.Однако компилятор отклонит код, который пытается инициализировать объект callback_with_just_bool

. Почему это так, и есть ли чистый способ обойти это?Спасибо.

Редактировать: Конкретная причина, по которой я пытаюсь сделать это в реальном коде, заключается в системе событий.В систему событий поступают данные об отдельном объекте, который желает условно получать события (например, «если вы достаточно близки к источнику, вы получите звуковое событие»), а также данныепредоставил обратному вызову о событии (например, «шум 10 кГц при X200 Y200»).В большинстве случаев данные, необходимые для проверки требований, будут существовать внутри данных, предоставляемых для обратного вызова о событии, но я хотел предоставить дополнительную дополнительную структуру данных, если это не так.Следовательно, пользователь может указать «void», если ему не нужна эта дополнительная структура данных.

Ответы [ 6 ]

0 голосов
/ 24 ноября 2018

Существует предложение добавить "обычный void" к языку.

В нем void становится моностатным типом, который все другие типы неявно преобразуются в.

Вы можете эмулировать это с помощью

struct monostate_t {
  template<class T>
  monostate_t(T&&) {}
};

затем

using callback_with_just_bool = some_callback<monostate_t>;
auto my_callback_just_bool = callback_with_just_bool([](bool x, auto&&...)
{
});

работает примерно так, как вам нравится.

0 голосов
/ 23 ноября 2018

Другие ответы объяснили почему.Это отвечает «есть ли чистый способ обойти это?»

Что я обычно делаю для обратных вызовов - это использование lambdas.

std::function<void(void)> myfunc;

bool b = false;
int i = 42;

myfunc = [&]() { if (b) ++i; };
0 голосов
/ 23 ноября 2018

«Почему это так?»

Поскольку единственное разрешенное использование void в списке параметров - это показать, что функция не принимает никаких параметров.

С [функция] :

void

Указывает, что функция не принимает параметров, это точный синоним для пустого списка параметров: int f(void); и int f(); объявляют одну и ту же функцию.Обратите внимание, что тип void (возможно, cv-qualified) не может использоваться в списке параметров, иначе: int f(void, int); и int f(const void); являются ошибками (хотя могут использоваться производные типы, такие как void*)

«Есть ли чистый путь?»

Я бы предложил специализироваться на 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;
};
0 голосов
/ 23 ноября 2018

Шаблоны Variadic - один из способов сделать это:

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

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

Это даже чище с шаблоном псевдонимов:

template <class... T> using callback_type = std::function<void(bool, T...)>;

int main()
{
  callback_type<int> my_callback_with_int = [](bool x, int y)
  {
  }; //OK

  callback_type<> my_callback_just_bool = [](bool x)
  {
  }; //OK now too...
}
0 голосов
/ 23 ноября 2018

Вы можете создать специализацию:

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

template<>
class some_callback<void>
{
    std::function<void(bool)> myfunc;
};
0 голосов
/ 23 ноября 2018

Проблема не в том коде, который вы показали, а в том, что в C / C ++ вы не можете определить функцию f как

void f(bool b, void v) {}

Причина в том, что, как сказал @Peter Ruderman, void не является допустимым типом параметра.

...