没有使用重载模式对 std::visit() 的匹配函数调用

No matching function call to std::visit() using overload pattern

提问人:glades 提问时间:5/17/2023 最后编辑:glades 更新时间:5/17/2023 访问量:234

问:

我正在尝试在具有访问者重载模式的变体中调度变体。但是,我似乎无法将参数拟合到预期值。我得到这个(截断,有关更多输出,请参阅编译器资源管理器链接):

error: no matching function for call to 'visit ...'

这是我的代码。我忽略了什么?

演示

#include <variant>
#include <cstdio>

template <typename... Ts>
struct overload : Ts...
{
    using Ts::operator() ...;
};

int main() {

    struct StateA{};
    struct StateB{};
    struct StateC{};

    using state_type = std::variant<StateA, StateB, StateC>;
    auto state = state_type{StateA{}};

    struct EventA{};
    struct EventB{};

    struct WifiConnectedNote{};
    struct ErrorNote{};

    using QueueVariantType = std::variant<std::monostate, WifiConnectedNote, ErrorNote>;
    
    using event_type = std::variant<std::monostate, QueueVariantType, EventA, EventB>;
    auto event = event_type{EventA{}};

    for (size_t i=0; i < 10; i++) {
        state = std::visit(overload{
            [&](QueueVariantType&& variant, auto&& state_tmp) -> state_type {
                std::visit(overload{
                    [&](WifiConnectedNote&&, auto&&){
                        printf("WifiConnectedNote A\n");
                    },
                    [&](ErrorNote&&, auto&&){
                        printf("ErrorNote A\n");
                    },
                    [&](auto&&, auto&&){
                        printf("Other in Queue variant\n");
                    },
                }, std::forward<decltype(variant)>(variant), std::forward<decltype(state_tmp)>(state_tmp));
                return StateC{};
            },
            [&](auto&&, const StateA&) -> state_type {
                printf("State A\n");
                return StateC{};
            },
            [&](auto&&, const StateB&) -> state_type {
                printf("State B\n");
                return StateA{};
            },
            [&](auto&&, const StateC&) -> state_type {
                printf("State C");
                return StateB{};
            },
        }, std::move(event), state);
    }
}
C++ 运算符重载 访客模式

评论


答:

1赞 nick 5/17/2023 #1
  • 缺少 的外部重载情况。要么提供一个状态,要么从变体类型中删除状态。std::visitevent==std::monostate

      [&](std::monostate, auto&& ) -> state_type {
          ; // Do stuff here
      }
    
  • state_tmp内部未使用。如果我从 lambda 签名中删除它和 ,代码就会编译并运行。但这是你想要的吗?请记住,这不是变体类型本身,而是由外部 std::visit 解析的基础类型。这就是内部访问失败的原因。std::visitauto&&state_tmp

希望你能从这里拿走!

评论

0赞 glades 5/17/2023
谢谢,你是对的!有趣的是,我认为 auto&& 与任一状态结合作为第二个参数将捕获任何事件,因此 monostate 也会被捕获。为什么不是这样?
0赞 Red.Wave 5/17/2023
第一点C不成立。和 or 有什么区别。第二点是直接命中。monostateEventAEventB
1赞 nick 5/19/2023
@glades , @Red.Wave :我不知道为什么会不匹配(我同意它应该匹配),但事实是 gcc 不会编译。在网上搜索了一下,在这个话题上我没有找到任何东西,也许你运气更好。auto&&monostate