c++ - 自定义开关功能中的大量神秘错误

标签 c++ templates boost c++17 boost-hana

我正在尝试根据 the boost hana manual 中的 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 << "wat2hek\n"; }),
        case_("YOWZA!", []{ std::cout << "HooRah!\n"; }),

        default_([]{ std::cout << "Hello, World!\n"; })
    );
}

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

有人能给我指出正确的方向吗?

最佳答案

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

A function called as predicate(k), where k is a key of the structure, and returning whether k is the key of the element being searched for. In the current version of the library, the predicate has to return an IntegralConstant holding a value that can be converted to bool.

这对于 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

关于c++ - 自定义开关功能中的大量神秘错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43918498/

相关文章:

c++ - 用于稀疏数据查找的高效数据结构

c++ - 从模板子类调用模板基类的重写模板成员函数

c++ - boost::asio::socket 线程安全

c++ - Unicode 中的 boost::property_tree write_json

c++ - 带有复制构造函数的 enable_if

c++ - Boost:创建一组线程并等待它们的正确用法是什么?

c++ - 找出堆栈数组中的下一个整数是否相同

c++ - boost 1.66.0 : could not find boost libraries :boost_system, boost_filesystem,boost_thread,boost_date_time

c++ - QProcess 阻止 UI 更新

Magento 电子邮件模板 : $_item -> getDescription returns null