有没有像给定的一样的 std::optional_function
is there a std::optional_function like the given
我正在寻找像 swifts 这样的东西? 在 C++ 中为 std::function 运算符。 在过去的几年里,我越来越喜欢它。
我想要一个 std::optional_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 };
}
} ;
?
运算符在C++中也非常有效:
// let function be of type std::function or a function pointer
auto var = f ? f() : default_value;
如果你真的想要一个这样做的类型,标准库中没有这样的东西,但一个简单的函数就足以做你想做的事情(仅适用于不返回引用或 void 的函数(:
template<typename F, typename... Args, typename R = std::invoke_result_t<F, Args&&...>>
auto optionally_call(F&& f, Args&&... args) -> std::optional<R> {
return f ? R(std::forward<F>(f)(std::forward<Args>(args)...)) : std::nullopt;
}
通过一些元编程,可以支持此实现不支持的情况。
这是为了强调在创建泛型的整个类型时存在很多陷阱。有许多错误和性能问题,甚至无法在示例代码中调用的代码。简单的实用程序函数将比类型更容易。
标准库没有类似的东西,但你可以自己构建一个:
#include <functional>
#include <iostream>
#include <optional>
template <typename T>
class optional_function {
private:
std::optional<T> func;
public:
optional_function(T f) : func{std::move(f)} {}
optional_function() = default;
template <typename... Args>
auto operator()(Args&&... args) const {
using func_invoke_type = decltype((*func)(std::forward<Args>(args)...));
constexpr bool func_invoke_type_is_void = std::is_same_v<void, func_invoke_type>;
using optional_result_type = std::optional<
std::conditional_t<
func_invoke_type_is_void, // Can't have a std::optional<void>
char,
std::conditional_t<
std::is_reference_v<func_invoke_type>, // Can't have a std::optional<T&>
std::reference_wrapper<std::remove_reference_t<func_invoke_type>>,
func_invoke_type
>
>
>;
if (func) {
if constexpr (!func_invoke_type_is_void) {
return optional_result_type{(*func)(std::forward<Args>(args)...)};
} else {
(*func)(std::forward<Args>(args)...);
return optional_result_type{ ' ' }; // can't return void{} '
}
}
return optional_result_type{};
}
};
// Test it
void foo() {}
int main() {
optional_function f1{[](int i) { return i * i; }};
optional_function f2{[] { std::cout << "Hello Worldn"; }};
decltype(f1) f3{};
optional_function f4{[](int a, const int& b) -> int const& {
std::cout << a + b << 'n';
return b;
}};
optional_function f5{foo};
auto res1 = f1(9);
auto res2 = f2();
auto res3 = f3(9);
int b = 5;
auto res4 = f4(1, b);
auto res5 = f5();
std::cout << std::boolalpha;
std::cout << "f1 is executed: " << res1.has_value() << ". result: " << *res1
<< 'n';
std::cout << "f2 is executed: " << res2.has_value() << 'n';
std::cout << "f3 is executed: " << res3.has_value() << 'n';
std::cout << "f4 is executed: " << res4.has_value() << ". result: " << *res4
<< 'n';
std::cout << "f5 is executed: " << res5.has_value() << 'n';
}
不,C++ 标准库中目前没有这样的东西。
相关文章:
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 有没有像给定的一样的 std::optional_function
- 从 boost::variant 中逐个索引获取项目,就像使用 std::variant 一样
- 如何将值插入到 c++ boost::multiindex 集合的特定索引中,就像在 std::list 中一样
- 将参数传递给成员函数,就像使用 std::cout 一样
- 使更长的 std::array 可访问,就好像它更短一样
- c++ std 的 inf 的行为是否与常识无穷大完全一样
- IS STD ::功能与使用自动一样有效
- std::launch::async就像同步进程一样阻塞
- 有没有一种方法可以使用std::array与文字或初始值设定项列表进行比较,就像使用赋值一样
- 为什么我们不能像使用 1D 和 2D 数组一样使用 std::fill()?
- 是否可以像数组一样处理 std::vector
- std::string() 和 std::string( " " ) 一样吗
- 输入Std::cin与直接赋值Std::string变量不一样
- std::vector可以像数组一样处理吗?
- 是否存在std::search对应的函数,就像std::count对应std::find一样
- 像数组一样访问std::map的std::映射