Использовать "noexcept" в std::function?

Этот код компилируется и запускается, бросая int:

#include <functional>

void r( std::function<void() noexcept> f ) { f(); }

void foo() { throw 1; }

int main()
{
    r(foo);
}

Однако я хотел бы, чтобы компилятор отклонил строку r(foo); так как r должен быть передан только noexcept функция. noexcept Спецификатор, кажется, игнорируется. Есть ли способ добиться этого?

Редактировать: Этот вопрос отличается от того, должны ли знания о noexcept-ness быть переданы при передаче указателя функции? потому что я прошу средства правовой защиты, особенно в случае std::function,

1 ответ

Решение

Я также наткнулся на эту проблему. Мое решение состояло в том, чтобы использовать делегирующий объект (делегирование функции std::). У делегата есть спецификация "кроме". Это все еще можно улучшить (добавить ход и т. Д.).

Вот оно...

#include <functional>

template <class FuncT>
struct NoExceptDelegate;

template <class R, class ... Args >
struct NoExceptDelegate<R(Args...)>
{
    NoExceptDelegate(std::function<R(Args...)>&& callback)
      : callback_(move(callback))
    {
      if (!callback_)
      {
        throw std::invalid_argument( "NoExceptDelegate requires a valid callback");
      }
    }

    NoExceptDelegate(const NoExceptDelegate& other)
      : callback_(other.callback_)
    {
    }

    NoExceptDelegate& operator=(const NoExceptDelegate& other)
    {
      if (this != &other)
      {
        callback_ = other.callback_;
      }
      return *this;
    }

    NoExceptDelegate(NoExceptDelegate&& other)
      : callback_(move(other.callback_))
    {
    }

    NoExceptDelegate& operator=(NoExceptDelegate&& other)
    {
      callback_ = move(other.callback_);
      return *this;
    }

    template <class...ArgsU>
    R operator()(ArgsU&&... args) noexcept
    {
      return callback_(std::forward<ArgsU>(args)...);
    }

  private:
    std::function<R(Args...)> callback_;
};

Это обычно используется в качестве контракта в асинхронном интерфейсе, чтобы указать, что предоставленный обработчик не должен выдавать, например:

struct Interface
{
  virtual void doSomethingAsynchronous(
    NoExceptDelegate<void(int)> onCompletionResult) = 0;
  //...etc
};

Поскольку клиент является поставщиком обратного вызова, NoExceptDelegate - это обещание поставщика, которое не должно завершиться сбоем. Поставщик должен убедиться, что по крайней мере предоставленная функция std::function является вызываемой.

Другие вопросы по тегам