gpt4 book ai didi

C++17 推断基于 lambda 的访问者的返回类型

转载 作者:行者123 更新时间:2023-12-01 14:49:30 27 4
gpt4 key购买 nike

这是 https://en.cppreference.com/w/cpp/utility/variant/visit 中给出的基于 lambda 重载的访问者:

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
std::visit(overloaded {
[](auto arg) { std::cout << arg << ' '; },
[](double arg) { std::cout << std::fixed << arg << ' '; },
[](const std::string& arg) { std::cout << std::quoted(arg) << ' '; },
}, v);

哪里 vvariant并且它的所有类型都必须实现了 lambdas。

我想给 overloaded 添加一个函数具有与所有 lambda 相同的返回类型 (这是 visit(overloaded{...}, v) 的返回类型)。
类似于:
template<class... Ts> struct overloaded : Ts...
{
using Ts::operator()...;

common_type_t<decltype(declval<Ts>())...> test() const { return {}; }
};
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
auto r = std::visit(overloaded {
[](auto arg) { return 1; },
[](double arg) { return 2; },
[](const std::string& arg) { return 3; },
}, v);

这里出了点问题, common_type<_Tp...>::type不存在。
我想过用 common_type_t<invoke_result_t<Ts>...>但我没有 lambdas 的参数,所以 invoke_result<Ts..>>::type在那里失败。

我错过了什么?

最佳答案

这个问题没有通用的解决方案,因为如果 lambda 表达式之一是通用的,例如

[](auto arg) { return arg; }

那么没有 std::variant 就无法推导出返回类型目的。

但是,我们可以尝试从具有非模板 operator() 的那些 lambda 表达式中推导出通用类型。 .这种特殊情况的解决方案如下。

首先创建一个推导 lambda 返回类型的特征,或者返回 empty如果扣除失败:
struct empty {};

template<typename Ret, typename Fn, typename Arg>
Ret return_type(Ret(Fn::*)(Arg));

template<typename Ret, typename Fn, typename Arg>
Ret return_type(Ret(Fn::*)(Arg) const);

template<typename Fn>
auto return_type(Fn) -> decltype(return_type(&Fn::operator()));

empty return_type(...);

然后调整 std::common_type :
template<>
struct std::common_type<empty, empty> {
using type = empty;
};

template<typename T>
struct std::common_type<T, empty> {
using type = T;
};

template<typename T>
struct std::common_type<empty, T> {
using type = T;
};

最后把所有这些放在一起:
template<class... Ts> struct overloaded : Ts... {
using Ts::operator()...;
static auto test() ->
std::common_type_t<decltype(return_type(std::declval<Ts>()))...>;
};

例子:
auto fn = overloaded {
[](auto arg) { },
[](int arg) { return 0; },
[](std::string) { return 1.; }
};

static_assert(std::is_same_v<decltype(fn.test()), double>);

如果不能推导出类型,返回类型 test()将是 empty :
auto fn = overloaded {
[](auto arg) { }
};

static_assert(std::is_same_v<decltype(fn.test()), empty>);

关于C++17 推断基于 lambda 的访问者的返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59007440/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com