diff --git a/include/xtensor/xoperation.hpp b/include/xtensor/xoperation.hpp index 44d639130..13c78a665 100644 --- a/include/xtensor/xoperation.hpp +++ b/include/xtensor/xoperation.hpp @@ -81,6 +81,43 @@ namespace xt } \ } +// This functor avoids implicit conversions of small integral types to 'int' +// by returning the same type instead of 'auto'. +#define UNARY_BITWISE_OPERATOR_FUNCTOR(NAME, OP) \ + struct NAME \ + { \ + template \ + constexpr std::decay_t operator()(const A1& arg) const \ + { \ + return OP arg; \ + } \ + template \ + constexpr auto simd_apply(const B& arg) const \ + { \ + return OP arg; \ + } \ + } + +// This functor avoids implicit conversions of small integral types to 'int' +// by returning the largest type instead of 'auto'. +#define BINARY_BITWISE_OPERATOR_FUNCTOR(NAME, OP) \ + struct NAME \ + { \ + template \ + constexpr std:: \ + conditional_t<(sizeof(std::decay_t) > sizeof(std::decay_t)), std::decay_t, std::decay_t> \ + operator()(T1&& arg1, T2&& arg2) const \ + { \ + using xt::detail::operator OP; \ + return (std::forward(arg1) OP std::forward(arg2)); \ + } \ + template \ + constexpr auto simd_apply(const B& arg1, const B& arg2) const \ + { \ + return (arg1 OP arg2); \ + } \ + } + namespace detail { DEFINE_COMPLEX_OVERLOAD(+); @@ -112,10 +149,10 @@ namespace xt BINARY_OPERATOR_FUNCTOR(logical_or, ||); BINARY_OPERATOR_FUNCTOR(logical_and, &&); UNARY_OPERATOR_FUNCTOR(logical_not, !); - BINARY_OPERATOR_FUNCTOR(bitwise_or, |); - BINARY_OPERATOR_FUNCTOR(bitwise_and, &); - BINARY_OPERATOR_FUNCTOR(bitwise_xor, ^); - UNARY_OPERATOR_FUNCTOR(bitwise_not, ~); + BINARY_BITWISE_OPERATOR_FUNCTOR(bitwise_or, |); + BINARY_BITWISE_OPERATOR_FUNCTOR(bitwise_and, &); + BINARY_BITWISE_OPERATOR_FUNCTOR(bitwise_xor, ^); + UNARY_BITWISE_OPERATOR_FUNCTOR(bitwise_not, ~); BINARY_OPERATOR_FUNCTOR(left_shift, <<); BINARY_OPERATOR_FUNCTOR(right_shift, >>); BINARY_OPERATOR_FUNCTOR(less, <);