检测运算符是否存在并且可以在c中调用(考虑static_asserts)
给定2种类型T和U我想检测是否可以在对象之间调用operator *(即可以写t * u,其中t是T类型而u是U类型)
我正在使用c++ detection idiom,但由于它在我的编译器中尚未提供,我自己就像这样实现了它 struct nonesuch { nonesuch() = delete; ~nonesuch() = delete; nonesuch(nonesuch const&) = delete; void operator=(nonesuch const&) = delete; }; namespace detail { template <class Default,class AlwaysVoid,template<class...> class Op,class... Args> struct detector { using value_t = std::false_type; using type = Default; }; template <class Default,class... Args> struct detector<Default,std::void_t<Op<Args...>>,Op,Args...> { using value_t = std::true_type; using type = Op<Args...>; }; } // namespace detail template <template<class...> class Op,class... Args> using is_detected = typename detail::detector<nonesuch,void,Args...>::value_t; template< template<class...> class Op,class... Args > constexpr bool is_detected_v = is_detected<Op,Args...>::value; 现在我有这样的帮手: template <typename T,typename U> using multiply = decltype(std::declval<T>() * std::declval<U>()); 并检测我是否可以调用它 bool can_multiply = is_detected_v<multiply,T,U> 它几乎没问题,例如按预期打印1,0 std::cout << is_detected_v<multiply,int,int> << std::endl; std::cout << is_detected_v<multiply,std::vector<int>,std::vector<int>> << std::endl; 但现在我上课了 template<typename T> class A { }; template<typename T> A<T> operator*(const A<T>&,const A<T>&) { static_assert(!std::is_same<bool,T>::value); return A<T>(); } 这里A< bool>不能乘以A< bool>但我的代码检测到它是可能的 std::cout << is_detected_v<multiply,A<bool>,A<bool>> << std::endl; // 1 A<bool>() * A<bool>(); // does't compile 所以,我的问题是,如何修复我的代码,以便在static_asserted出来时不检测方法?我想我可以用一些sfinae替换static_assert但我不想(因为我没有访问权限,除了static_asserts有更好的错误消息). 解决方法
你根本做不到.这只是static_assert的缺点之一 – 无法从外部验证操作的有效性.那是因为static_assert不会发生在operator *的实例化的“直接上下文”中,所以SFINAE不适用 – 它总是一个硬错误.
我同情.但这基本上是权衡取舍. SFINAE和类型检查,或static_assert和更清晰的错误. (当然在这种情况下你可以写一个非模板A< bool>运算符*(A< bool> const&,A< bool> const&)但这可能除此之外). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |