mardi 24 mai 2016

C++ SFINAE operator/function result type check

I am writing a template-based class for Polynomials. (Evaluation, some operations between Polynomials, differentiation, ...), like this: template <typename _ty> class Polynomial{...

For the to_string function (and the std::ostream-left-shift-override), I had to check, if _ty supports the <-operator (i.e. yes for real numbers, no for complex numbers), so that the string could be formatted nicely. For this I use this code:

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

In short, is_ineq_supported(type) returns an std::true_type if there is a valid overload for the <-operator, and a false_type if not. The corresponding functions can then be called with a true_type or false_type as the distinguishing argument, like this:

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));
}

I also have a Vector class, that overloads the binary *-operator with the dot product, so it returns a double. But for a polynomial, it only makes sense, to have coefficients and arguments, which return the same type when multiplied with one another.

My problem is the following: I'd like to have a way of checking, if the given operation returns a specified type. (maybe a similar macro?) I think, the simplest would be something that returns a true_type if the result type matches the argument type and a false_type otherwise. Of course, more general solutions are even better.

In case, the IDE and Compiler matter: I'm using Visual Studio 2015 with default settings.

Aucun commentaire:

Enregistrer un commentaire