自定义开关功能中存在大量神秘错误



我正在尝试根据boost hana手册中的any类型开关示例编写一个任意值开关。

我以前成功地做到了这一点,但现在似乎无法完成它。

我真的想弄清楚我的解决方案到底出了什么问题,所以事不宜迟:

struct default_val{
    constexpr bool operator ==(const auto&) const noexcept{ return false; }
    constexpr bool operator !=(const auto&) const noexcept{ return true; }
    constexpr bool operator ==(default_val) const noexcept{ return true; }
    constexpr bool operator !=(default_val) const noexcept{ return false; }
};
template<typename Fn>
auto default_(Fn fn){
    return hana::make_pair(default_val{}, fn);
}
template<typename Val, typename Fn>
auto case_(Val val, Fn fn){
    return hana::make_pair(val, fn);
}
template<typename Val, typename Default>
decltype(auto) process(Val&&, Default &&def){
    return hana::second(std::forward<Default>(def))();
}
template<typename Val, typename Default, typename Case, typename ... Rest>
decltype(auto) process(Val &&val, Default &&def, Case &&cas, Rest &&... rest){
    if(std::forward<Val>(val) == hana::first(std::forward<Case>(cas)))
        return hana::second(std::forward<Case>(cas))();
    else
        return process(std::forward<Val>(val), std::forward<Default>(def), std::forward<Rest>(rest)...);
}
template<typename Val>
auto switch_(Val val){
    return [val](auto ... cases){
        auto cases_ = hana::make_tuple(cases...);
        auto default_ = hana::find_if(cases_, [](const auto &c){
            return
                hana::type_c<default_val> ==
                hana::type_c<std::decay_t<decltype(hana::first(c))>>;
        });
        static_assert(default_ != hana::nothing);
        auto rest_ = hana::filter(cases_, [](const auto &c){
            return
                hana::type_c<default_val> !=
                hana::type_c<std::decay_t<decltype(hana::first(c))>>;
        });
        return hana::unpack(rest_, [&](const auto &... rest){
            return process(val, default_, rest...);
        });
    }
}

这应该像any示例一样使用,但带有值:

#include "myswitch.hpp"
int main(){
    std::string input;
    std::cin >> input;
    switch_(input)(
        case_("yowza", []{ std::cout << "where's the enthusiasm?n"; }),
        case_("Yowza", []{ std::cout << "wat2hekn"; }),
        case_("YOWZA!", []{ std::cout << "HooRah!n"; }),
        default_([]{ std::cout << "Hello, World!n"; })
    );
}

但是我得到了一个关于在switch_中分配default_时在扣除auto之前使用hana::find_if_t::operator()(Xs&&, Pred&&)的 veeeery 长而神秘的错误.

有人可以在这里指出我正确的方向吗?

根据Boost.Hana的谓词手册(强调我的(:

一个称为谓词 (k( 的函数,其中 k 是结构的键,并返回 k 是否是要搜索的元素的键。在库的当前版本中,谓词必须返回一个 IntegralConstant,其中包含一个可以转换为布尔值的值

这对于hana::find_ifhana::filter使用的谓词都是必需的。

对于您的default_val类型,可以实现可以更改为以下内容:

struct default_val {
    template <typename T>
    constexpr auto operator ==(const T&) const noexcept{ return hana::false_c; }
    template <typename T>
    constexpr auto operator !=(const T&) const noexcept{ return hana::true_c; }
    constexpr auto operator ==(default_val) const noexcept{ return hana::true_c; }
    constexpr auto operator !=(default_val) const noexcept{ return hana::false_c; }
};

我使用 Clang 3.9 运行了您的代码,它通过以下附加调整将值解开default_可选值中的包装,效果很好。

        return hana::unpack(rest_, [&](const auto &... rest){
        return process(val, *default_, rest...);
                         // ^ Note the added dereference operator here

相关内容

最新更新