自定义开关功能中的大量神秘错误
Massive cryptic error in custom switch function
我正在尝试根据 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_
.[=19= 中分配 default_
时,在扣除 auto
之前,我得到了一个关于使用 hana::find_if_t::operator()(Xs&&, Pred&&)
的非常长且非常神秘的错误]
有人能给我指出正确的方向吗?
根据 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_if
和 hana::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
我正在尝试根据 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_
.[=19= 中分配 default_
时,在扣除 auto
之前,我得到了一个关于使用 hana::find_if_t::operator()(Xs&&, Pred&&)
的非常长且非常神秘的错误]
有人能给我指出正确的方向吗?
根据 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_if
和 hana::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