[英]C++ SFINAE operator/function result type check
我正在为多项式编写基于模板的类。 (求值,多项式之间的一些运算,微分,...),如下所示: template <typename _ty> class Polynomial{...
对于to_string
函数(和std::ostream
-left-shift-override),我不得不检查_ty
支持<
-operator(即,对于实数为yes,对于复数为no),以便该字符串可以为格式很好。 为此,我使用以下代码:
#include <type_traits>
template <class _op, class... _ty, typename = decltype(std::declval<_op>()(std::declval<_ty>()...))>
std::true_type impl_test(const _op&, const _ty&...) { return std::true_type(); }
std::false_type impl_test(...) { return std::false_type(); }
template <class> struct supports;
template <class _op, class... _ty> struct supports<_op(_ty...)> : decltype(impl_test(std::declval<_op>(), std::declval<_ty>()...)){};
#define is_ineq_supported(type) supports<std::less<>(type, type)>()
简而言之,如果<
std::true_type
有有效的重载,则is_ineq_supported(type)
返回std::true_type
否则返回false_type
。 然后可以使用true_type
或false_type
作为区别参数来调用相应的函数,如下所示:
template <typename _ty> void do_stuff(_ty arg, const std::true_type&) {
// do stuff with the '<'-operator
}
template <typename _ty> void do_stuff(_ty arg, const std::false_type&) {
// do stuff without the '<'-operator
}
template <typename _ty> void do_stuff(_ty arg) {
do_stuff(arg, is_ineq_supported(_ty));
}
我也有一个Vector类,它用点积重载了二进制*
-operator,因此它返回double
。 但是对于一个多项式来说,只有系数和自变量相乘时才返回相同的类型,这才有意义。
我的问题如下:如果给定的操作返回指定的类型,我想有一种检查方法。 (也许是类似的宏?)我认为,如果结果类型与参数类型匹配,则最简单的方法将返回true_type
否则返回false_type
。 当然,更一般的解决方案甚至更好。
万一IDE和编译器很重要:我在使用Visual Studio 2015(默认设置)。
这是一个使用fit::is_callable
的通用跨平台解决方案,它将最终添加到Boost中。 另外,请注意C ++ 17中的std::is_callable
。
不需要宏:
#include <type_traits>
#include <iostream>
#include <fit/is_callable.hpp>
// std::less doesn't SFINAE, so we make our own test
struct less_test {
template<typename L, typename R>
auto operator()(L l, R r) -> decltype(l < r);
};
template<typename T>
using is_less_than_comparable = fit::is_callable<less_test, T, T>;
// operator< version (replace with your implementation)
template <typename T> constexpr auto
do_stuff(T arg, const std::true_type&) {
return std::integral_constant<int, 0>{};
}
// other version (replace with your implementation)
template <typename T> constexpr auto
do_stuff(T arg, const std::false_type&) {
return std::integral_constant<int, 1>{};
}
template <typename T> constexpr auto
do_stuff(T arg) {
return do_stuff(arg, is_less_than_comparable<T>{});
}
struct foo {};
int main() {
//is not less-than comparable
static_assert(do_stuff(foo{}) == 1, "");
//is less-than comparable
static_assert(do_stuff(0) == 0, "");
}
您可能应该重新考虑成员方法检测器,并使用大多数基于C ++ 11的 void_t
解决方案。
就是说,如果我必须更新您的解决方案,则以下代码可能是一种可行的方法:
template <class _op, class _ret, class... _ty>
typename std::enable_if<std::is_same<decltype(std::declval<_op>()(std::declval<_ty>()...)), _ret>::value, std::true_type>::type
impl_test(const _op&, const _ty&...) {
return std::true_type();
}
这将如下工作:
struct S { int operator()() { return 42; } };
int main() {
assert((impl_test<S, int>(S{})));
// this will give you an error at compile time
// assert((impl_test<S, double>(S{})));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.