是否可以为 std::variant
重载 operator||
,如果替代类型有这样的操作符就使用它,如果替代类型没有定义这样的操作符则抛出异常?
到目前为止,我得到了类似的东西:
template<typename ...Ts>
constexpr bool operator||(std::variant<Ts...> const& lhs, std::variant<Ts...> const& rhs)
{
return /*no idea */;
}
最佳答案
首先,使用 SFINAE 编写一个包装器,在可能的情况下调用运算符,否则抛出异常:
struct Invalid :std::exception { };
struct Call_operator {
template <typename T, typename U>
constexpr auto operator()(T&& a, U&& b) const
noexcept(std::is_nothrow_invocable_v<std::logical_or<>, T, U>)
-> decltype(static_cast<bool>(std::declval<T>() || std::declval<U>()))
{
return std::forward<T>(a) || std::forward<U>(b);
}
[[noreturn]] bool operator()(...) const
{
throw Invalid{};
}
};
然后,使用访问
,尊重noexcept:
template <typename T, typename... Ts>
struct is_nothrow_orable_impl
:std::conjunction<std::is_nothrow_invocable<Call_operator, T, Ts>...> {};
template <typename... Ts>
struct is_nothrow_orable
:std::conjunction<is_nothrow_orable_impl<Ts, Ts...>...> {};
template<typename ...Ts>
constexpr auto operator||(std::variant<Ts...> const& lhs, std::variant<Ts...> const& rhs)
noexcept(is_nothrow_orable<Ts...>::value)
-> decltype(std::visit(Call_operator{}, lhs, rhs))
{
return std::visit(Call_operator{}, lhs, rhs);
}
( live demo )
关于c++ - 运算符|| std::variant 的重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57267813/