Я ищу что-то вроде стрижей? оператор в c ++ для std :: function. Мне нравилось это за последние пару лет.
Мне бы хотелось, чтобы std :: option_function вызывала функцию, только если функция существует.
Что-то вроде этого (но написано боги c ++):
template<typename R>
struct option_function_result {
bool executed;
R result;
} ;
template<>
struct option_function_result<void>
{
bool executed;
} ;
template<typename F>
class optional_function
{
public:
typedef std::function<F> function_type;
typedef option_function_result<typename function_type::result_type> result_type;
protected:
function_type f;
public:
template<typename Fn>
optional_function operator=(const Fn &f_)
{
f = f_;
return *this;
}
template<typename Fn>
optional_function operator=(Fn &&f_)
{
f = std::forward<Fn>(f_);
return *this;
}
operator bool() const
{
return (bool)f;
}
template<typename ...Args, typename R>
result_type operator()(Args... args)
{
if (f)
return result_type { true, f(args...) };
return result_type { false };
}
template<typename ...Args>
result_type operator()(Args... args)
{
if (f)
{
f(args...);
return result_type { true };
}
return result_type { false };
}
} ;
Еще одна ревизия
Вот ревизия 2. Чтобы не задавать вопрос, и поскольку я не знаю, будет ли это окончательным ответом Я собираюсь разместить его здесь сейчас:
Я ожидаю, что конструктор для структуры не является необходимым. Однако это вынуждает компилятор выдавать мне ошибки, которые мне нужны для отладки компиляции.
template<typename R>
struct optional_function_result {
bool executed;
R result;
optional_function_result(bool &&executed_, R &&result_) :
executed (executed_),
result(result_) {}
} ;
template<>
struct optional_function_result<void>
{
bool executed;
optional_function_result(bool &&executed_) :
executed (executed_) {}
} ;
template<typename F>
class optional_function
{
public:
typedef std::function<F> function_type;
typedef typename std::function<F>::result_type function_result_type;
typedef optional_function_result<typename function_type::result_type> result_type;
protected:
function_type f;
public:
template<typename Fn>
optional_function operator=(const Fn &f_)
{
f = f_;
return *this;
}
template<typename Fn>
optional_function operator=(Fn &&f_)
{
f = std::forward<Fn>(f_);
return *this;
}
operator bool() const
{
return (bool)f;
}
template<
typename ... Args,
typename FR=function_result_type,
typename std::enable_if<!std::is_void<FR>::value, FR>::type* = nullptr
>
result_type operator()(Args... args) const
{
if (f)
return {
true,
std::forward<typename function_type::result_type>(f(args...))
};
return {
false,
function_result_type()
};
}
template<
typename ... Args,
typename FR=function_result_type,
typename std::enable_if<std::is_void<FR>::value, FR>::type* = nullptr
>
result_type operator()(Args... args) const
{
if (f)
{
f(args...);
return { true };
}
return { false };
}
} ;
Хорошо, еще одна версия, которая использует, в основном, опционально, чтобы избавиться от некоторых крайних случаев.
template<typename T>
using optional_type = std::experimental::optional<T>;
template<typename R>
struct optional_function_result : optional_type<R> {
typedef optional_type<R> super_type;
optional_function_result() :
super_type() {}
optional_function_result(R &&result_) :
super_type(result_) {}
bool executed() const { return this->has_result(); }
} ;
template<>
struct optional_function_result<void>
{
bool executed_;
optional_function_result(bool &&executed__) :
executed_ (executed__) {}
bool executed() const { return executed_; }
} ;
template<typename F>
class optional_function
{
public:
typedef std::function<F> function_type;
typedef typename std::function<F>::result_type function_result_type;
typedef optional_function_result<typename function_type::result_type> result_type;
protected:
function_type f;
public:
template<typename Fn>
optional_function operator=(const Fn &f_)
{
f = f_;
return *this;
}
template<typename Fn>
optional_function operator=(Fn &&f_)
{
f = std::forward<Fn>(f_);
return *this;
}
operator bool() const
{
return (bool)f;
}
template<
typename ... Args,
typename FR=function_result_type,
typename std::enable_if<!std::is_void<FR>::value, FR>::type* = nullptr
>
result_type operator()(Args... args) const
{
if (f)
return {
std::forward<typename function_type::result_type>(f(args...))
};
return {};
}
template<
typename ... Args,
typename FR=function_result_type,
typename std::enable_if<std::is_void<FR>::value, FR>::type* = nullptr
>
result_type operator()(Args... args) const
{
if (f)
{
f(args...);
return { true };
}
return { false };
}
} ;