gpt4 book ai didi

c++ - 变体访问和 common_type

转载 作者:可可西里 更新时间:2023-11-01 18:27:52 27 4
gpt4 key购买 nike

我想知道如何 std::visit返回类型转换应该有效。

上下文如下:我有一个变体对象,我想根据其基础类型应用(通过 std::visit )不同的函数。每个函数的结果可能有不同的类型,但我希望 std::visit 将它打包成一个变体类型。

伪代码:

我有:

variant<A,B> obj
f(A) -> A
f(B) -> B

我要:

if obj is of type A => apply f(A) => resA of type A => pack it in variant<A,B>
if obj is of type B => apply f(B) => resB of type B => pack it in variant<A,B>

现在,根据cppreference ,std::visit 的返回类型是“访问者的选定调用返回的值,转换为所有可能的 std::invoke 表达式的通用类型”但是没有指定普通类型的含义。是std::common_type ?在这种情况下,它不适用于 gcc 7.2:

#include <variant>
#include <iostream>
#include <type_traits>

struct A {
int i;
};
struct B {
int j;
};

// the standard allows to specialize std::common_type
namespace std {
template<>
struct common_type<A,B> {
using type = std::variant<A,B>;
};
template<>
struct common_type<B,A> {
using type = std::variant<A,B>;
};
}


struct Functor {
auto
operator()(A a) -> A {
return {2*a.i};
}
auto
operator()(B b) -> B {
return {3*b.j};
}
};


int main() {
std::variant<A,B> var = A{42};

auto res = std::visit( Functor() , var ); // error: invalid conversion from 'std::__success_type<B>::type (*)(Functor&&, std::variant<A, B>&) {aka B (*)(Functor&&, std::variant<A, B>&)}' to 'A (*)(Functor&&, std::variant<A, B>&)' [-fpermissive]

}

我应该如何表达这种解包-申请访问-重新打包模式?

注意事项:

1) 专攻 std::common_type<A(*)(Ts...),B(*)(Ts...)>不会削减它。这可以解决问题,但依赖于特定的 std::lib 实现细节。 此外,它不适用于多次访问。

2)我给出的例子真的是精简到最低限度,但是你要想象我要提供的访问机制是在图书馆端,而访问者是在客户端,可以任意复杂:未知数量和类型的参数,未知返回类型。图书馆应该只提供访问和一组预定义的 std::common_type用于访问返回类型的特化。例如,定义

auto f = [](auto x) -> variant<A,B> { return Functor()(x); };

然后申请std::visitf不是一个可行的选择:从图书馆的角度来看,我无法在不知道“打包”返回类型的情况下预定义这种 lambda。 [主要问题是我没有办法询问 std::common_type 的语言。一个特定的重载集]

最佳答案

您可以创建自己的 visit 层,例如:

template <typename Visitor, typename ... Ts>
decltype(auto) my_visit(Visitor&& vis, const std::variant<Ts...>& var)
{
return std::visit([&](auto&& e)
-> std::common_type_t<decltype(vis(std::declval<Ts>()))...>
{
return vis(e);
}, var);
}

Demo

关于c++ - 变体访问和 common_type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46103745/

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