Quantcast
Channel: Recent Questions - Stack Overflow
Viewing all articles
Browse latest Browse all 18095

Expression templates cppcon 2019

$
0
0

I am looking at Bowie Owens' cppcon 2019 talk -- the can be found slides here. I came accross this talk as I was interested in introducing expression templates for a in-house numerical matrix-vector library that I am using, to improve its performance as well as the semantics of its client code.

I am not an expert in C++ and the talk's source code is not provided, so that I used the slides' example code snippets and came up with this :

//is_array_v    template <class T> struct is_array {    static constexpr bool value = false;};template <class T>struct is_array<std::vector<T>> {    static constexpr bool value = true;};template <class T>constexpr bool is_array_v =    is_array<std::remove_cvref_t<T>>::value;struct expression {};template <class callable, class... operands>class expr : public expression{    // I used reference semantics as I wish to avoid copying    // but pay attention not to use ref to a temp    // after the lifetime of the temp ended ...    // I use variadic template to tackle any arity operator at once    // and this mitigates the need for CRTP    std::tuple<operands const &...> args_;    callable f_;public:    expr(callable f, operands const&... args)        : args_(args...), f_(f) {}    auto operator[](size_t const i) const    {        auto const call_at_index =            [this, i](operands const&... a)                {                return f_(subscript(a, i)...);            };        return std::apply(call_at_index, args_);    }};template <class T>constexpr bool is_array_or_expression =    is_array_v<T> ||    std::is_base_of_v<expression, std::remove_cvref_t<T>>;template <class A, class B>constexpr bool is_binary_op_ok =    is_array_or_expression<A> ||    is_array_or_expression<B>;//subscript()template <class operand>auto subscript(operand const& v, size_t const i) {    if constexpr (is_array_or_expression<operand>) {        return v[i];    }    else {        return v;    }}template <class LHS, class RHS>auto operator+(LHS const & lhs, RHS const& rhs){    // I use a lambda so that everything is located in ONE place    return expr{        [](auto const& l, auto const& r)        {            return l + r; // deduced return types         }, lhs, rhs    };}class tridiagonal{    std::vector<double> v_;public:    tridiagonal(std::vector<double> v) : v_(std::move(v)) {}    template <class src_type>    tridiagonal& operator=(src_type const& src)    {        size_t const I = v_.size();        for (size_t i = 0; i < I; ++i) {            v_[i] = src[i];        }        return *this; // this line was missing in the slides and in the talk    }};

Yet when I write client code :

tridiagonal a({ 1.0, 2.0, 3.0 });tridiagonal b({ 0.5, 0.25, -4.5 });tridiagonal c = a + b; // problematic line

at compilation the compiler tells me, on the problematic line, that :

Error   C2440   'initializing': cannot convert from '+::<lambda_1>,LHS,RHS>' to 'tridiagonal'with[    LHS=tridiagonal,    RHS=tridiagonal}

Viewing all articles
Browse latest Browse all 18095

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>