【问题标题】:Massive cryptic error in custom switch function自定义开关功能中的大量神秘错误
【发布时间】:2017-05-11 14:35:06
【问题描述】:

我正在尝试根据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"; })
    );
}

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

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

【问题讨论】:

  • 请添加实际错误。此外,如果您减少示例程序会很有帮助 - 错误在您的 find_if 本身中。因此,例如,该声明之外的所有内容都与您的问题无关。
  • @Barry 我真的不确定这是不是,错误是巨大的。但如果有帮助,我会添加它(未编辑)。
  • @Barry 这是一个 pastebin 链接,不值得放在这里。模板倾向于对 GCC 这样做(甚至仍然如此)。 pastebin.com/QBcKbDcK
  • @CoffeeandCode 不,将其复制到代码块中。只需以&gt; 为前缀,后跟 ... 5 或 6 个空格 ... 以使其格式正确(它将显示为代码引用)。我们会有滚动条和所有东西,它会显示在搜索中,它不会依赖于可用的 pastebin 和所有好东西。
  • @Yakk 是的,但是错误早就超过了stackoverflow的字符限制。此外,我通常会粘贴整个内容,突出显示它,然后按 Ctrl+K:这样会容易得多。

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


【解决方案1】:

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

一个称为 predicate(k) 的函数,其中 k 是结构的键,并返回 k 是否是正在搜索的元素的键。在当前版本的库中,谓词必须返回一个 IntegralConstant,其中包含一个可以转换为 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

【讨论】:

  • 如果我比较它们的 typescompile-time 值,我会得到完全相同的错误消息。
  • @CoffeeandCode bool 不满足 IntegralConstant
  • @CoffeeandCode 唯一荒谬的是你的态度。长大。 IntegralConstant 是 Hana 宇宙中的一个概念,它意味着非常具体的东西。
  • @CoffeeandCode:“积分型”与hana::IntegralConstant不同。
  • 非常感谢@JasonRice!我知道这最终会变得平庸。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-08
相关资源
最近更新 更多