检测操作符是否存在并可在c++中调用(考虑static_assertions)
Detect whether operator exists and callable in c++ (considering static_asserts)
给定2种类型T
和U
,我想检测是否可以在这些对象之间调用operator *
(即是否可以编写t * u
,其中t
为T
类型,u
为U
类型)
我正在使用c++检测习惯用法,但由于它在我的编译器中还不可用,所以我自己实现了它,像这样
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, template<class...> class Op, 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, Op, 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;
现在我有了class
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_断言有更好的错误消息)。
所以,我的问题是,如何修复我的代码不检测方法时,他们static_asserted ?
你就是不能。这只是static_assert
的缺点之一——没有办法从外部验证操作的有效性。这是因为static_assert
不会发生在operator*
实例化的"即时上下文中",因此SFINAE不适用-它将始终是一个硬错误。
我想我可以用一些sfinae代替static_assert,但我不想这样做(因为我没有访问权限,而且static_assert有更好的错误消息)。
我同情。但这基本上是一种权衡。SFINAE和类型检查,或static_assert
和更清晰的错误。(当然,在这种情况下,您可以只编写一个非模板A<bool> operator*(A<bool> const&, A<bool> const&)
,但这可能不是重点)。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 函数调用中参数的顺序重要吗
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 基于另一个成员参数将函数调用从类传递给它的一个成员
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在c++类上调用void函数
- 使用一个考虑到std::map中键值的滚动或换行的键
- 为什么 std::unique 不调用 std::sort?
- 调用专用模板时出错"no matching function for call to [...]"
- 选择要调用的构造函数
- C++为什么尽管我调用了void函数,它却不起作用
- 构造函数正在调用一个使用当前类类型的函数
- 变量没有改变?通过向量的函数调用
- C++:考虑但不调用构造函数的特殊性
- 优先考虑GRPC调用以避免服务器过载
- 为什么 C++ 中的函数重载解析会考虑静态调用的非静态成员函数
- 检测操作符是否存在并可在c++中调用(考虑static_assertions)
- 在 Big O 表示法中,您如何考虑对其他方法的调用