首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SFINAE算子过载

SFINAE算子过载
EN

Stack Overflow用户
提问于 2020-04-07 14:21:28
回答 1查看 112关注 0票数 0

我很难理解为什么下面的代码无法编译。该代码片段包含两个操作符&重载,一个用于库头中的某个可自定义枚举类,另一个用于某些应用程序代码。这两个重载都使用std::enable_if来限制传入的类型,我不知道哪里可能有任何歧义?当我删除第二个操作符&重载时,代码会编译。

代码语言:javascript
复制
#include <cstdint>
#include <type_traits>

// Boilerplate for enum class type trait
namespace detail {

template <typename, typename = void>
struct is_enum_class_impl : std::false_type {};

template <typename T>
struct is_enum_class_impl<T, decltype((void)+T{})> : std::true_type {};

}  // namespace detail

// Enum class type trait
template <typename T>
using is_enum_class = std::integral_constant<
    bool, !detail::is_enum_class_impl<std::remove_cvref_t<T>>::value &&
              std::is_enum<std::remove_cvref_t<T>>::value>;
template <typename T>
inline constexpr bool is_enum_class_v{is_enum_class<T>::value};

template <typename T>
struct is_enum_class_flag : std::false_type {};

template <typename T>
inline constexpr bool is_enum_class_flag_v{is_enum_class_flag<T>::value};

// First operator& overload for enum class
template <typename T>
constexpr auto operator&(T lhs, T rhs)
    -> std::enable_if_t<is_enum_class_v<T> && is_enum_class_flag_v<T>, T> {
  return static_cast<T>(static_cast<std::underlying_type_t<T>>(lhs) &
                        static_cast<std::underlying_type_t<T>>(rhs));
}

namespace io {

// Enum class type with user enabled operator overload
enum class E { A = 1u << 0u, B = 1u << 1u, C = 1u << 2u };

}  // namespace io

// Specialization to enable operator overload
template <>
struct is_enum_class_flag<io::E> : std::true_type {};

namespace io {

// Some user type plus trait
struct Mask{};
template <typename T>
using is_mask = std::is_same<std::remove_cvref_t<T>, Mask>;
template <typename T>
inline constexpr bool is_mask_v{is_mask<T>::value};

// Another user type plus trait
struct State{};
template <typename T>
using is_state = std::is_same<std::remove_cvref_t<T>, State>;
template <typename T>
inline constexpr bool is_state_v{is_state<T>::value};

template <typename T>
using is_mask_or_state = std::disjunction<is_mask<T>, is_state<T>>;
template <typename T>
inline constexpr bool is_mask_or_state_v{is_mask_or_state<T>::value};

// Second operator& overload for user types
template <typename T, typename U>
constexpr auto operator&(T lhs, U rhs) -> std::enable_if_t<
    std::conjunction_v<is_mask_or_state<T>, is_mask_or_state<U>>> {
  using R = std::conditional_t<is_mask_v<T> && is_mask_v<U>, Mask, State>;
  return static_cast<R>(lhs.value() & rhs.value());
}

// Function fails to compile
void foo() {
  io::E e{io::E::A};
  // Compiler complains about invalid operands to binary expression ('io::E' and 'io::E') ?
  auto const has_a{e & io::E::A};
}

}  // namespace io

这里还有一个链接,指向godbolt上的代码:https://godbolt.org/z/nezztu

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-07 14:32:57

实际上,您已经发布了ADL

无论是,

  • 添加using: void (){使用::操作符&;io:e{ io::E :a};auto has_a{e &io::e:a};} 演示
  • 或者在operator&中移动您的第一个namespace io演示
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61082222

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档