C++ SFINAE 运算符/函数结果类型检查

标签 c++ c++11 sfinae

我正在为多项式编写一个基于模板的类。 (评估,多项式之间的一些操作,微分,......),就像这样: template <typename _ty> class Polynomial{...

对于 to_string函数(和 std::ostream -left-shift-override),我必须检查,如果 _ty支持< - 运算符(即对于实数是,对于复数不是),以便可以很好地格式化字符串。为此,我使用此代码:

#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)>()

简而言之,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 类,它重载了二进制 * -运算符与点积,所以它返回一个 double .但对于多项式,只有系数和参数在相互相乘时返回相同类型才有意义。

我的问题如下: 我想要一种检查给定操作是否返回指定类型的方法。 (也许是类似的宏?)我认为,最简单的是返回 true_type 的东西如果结果类型匹配参数类型和 false_type否则。当然,更通用的解决方案更好。

以防万一,IDE 和编译器很重要:我使用的是默认设置的 Visual Studio 2015。

最佳答案

这是一个通用的跨平台解决方案,使用 fit::is_callable ,最终将添加到 Boost.还要留意 std::is_callable在 C++17 中。

不需要宏:

#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++ SFINAE 运算符/函数结果类型检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37412781/

相关文章:

c++ - 有符号和无符号之间的 SFINAE 区别

c++ - Vulkan:AMD vkCmdDebugMarkerBeginEXT 仅在 vkGetInstanceProcAddr 中找到

临时值的 C++ 模板类型推导

c++ - 以编程方式从父级的子进程中捕获打印,这样它们就不会转到标准输出

c++ - 为什么存在用户声明的析构函数时生成移动构造函数?

c++ - 使用 SFINAE 检测 constexpr

c++ - 什么是用数组(C 或 std::array)元素构造 C++ 元组的单行表达式?

c++ - 错误 : mismatched types: <function> and <lambda>

c++ - 将实例数组实现为不同类型的好方法是什么

c++ - 根据 std::tuple 的大小更改函数的返回类型