How can I combine templated derived class in CRTP with derived class expression templates?

staerkHelmis

My goal is to implement a vector class Vec that allows for efficient computation of arithmetic expressions like auto vecRes = vecA + vecB * vecC. This is a known problem and a solution using the Curiously Recurring Template Pattern (CRTP) can be found on wikipedia.

I started by adopting an implementation for hardcoded vector element type double including a derived class for addition,

template <typename Exn>
class VecExn
{
public:
    double operator[] ( int32_t idx ) const { return static_cast<Exn const&>( *this )[idx]; }
    int32_t size() const { return static_cast<Exn const&>( *this ).size(); }
};

class Vec: public VecExn<Vec>
{
public:
    Vec() {}
    Vec( std::initializer_list<double> iniLis ) : eles_( iniLis ) {  }
    template < typename Exn1 >
    Vec( VecExn<Exn1> const& exn ) : eles_( exn.size() )
    {
        for( int32_t idx = 0; idx < exn.size(); ++idx )
            eles_[idx] = exn[idx];
    }
    template < typename Exn1 >
    Vec& operator=( VecExn<Exn1> const& exn )
    {
        for( int32_t idx = 0; idx < exn.size(); ++idx )
            eles_[idx] = exn[idx];
        return *this;
    }

    double operator[] ( int32_t idx ) const { return eles_[idx]; }
    double& operator[] ( int32_t idx ) { return eles_[idx]; }
    int32_t size() const { return eles_.size(); };
private:
    std::vector<double> eles_;
};


template <typename Lhs, typename Rhs>
class VecSum: public VecExn<VecSum<Lhs, Rhs> >
{
public:
    VecSum( Lhs const& lhs, Rhs const& rhs ) : lhs_( lhs ), rhs_( rhs ) {}
    double operator[] ( int32_t idx ) const { return lhs_[idx] + rhs_[idx]; }
    int32_t size() const { return lhs_.size(); };
private:
    Lhs const& lhs_;
    Rhs const& rhs_;
};

which works as it should.

However, in my approach to replace double by a template, the base class gets a template template argument and the plain Vec becomes, of course, templated.

template < typename Typ, template<typename> typename Exn >
class VecExn
{
public:
    Typ operator[] ( int32_t idx ) const { return static_cast<Exn<Typ> const&>( *this )[idx];}
    int32_t size() const { return static_cast<Exn<Typ> const&>( *this ).size(); }
};

template <typename Typ>
class Vec: public VecExn<Typ, Vec >
{
public:
    Vec() {}
    Vec( std::initializer_list<Typ> iniLis ) : eles_( iniLis ) {  }
    template < typename Exn1 >
    Vec( VecExn<Exn1> const& exn ) :eles_(exn.size() )
    {
        for( int32_t idx = 0; idx < exn.size(); ++idx )
            eles_[idx] = exn[idx];
    }
    template < typename Exn1 >
    Vec& operator=( VecExn<Exn1> const& exn )
    {
        for( int32_t idx = 0; idx < exn.size(); ++idx )
            eles_[idx] = exn[idx];
        return *this;
    }

    Typ operator[] ( int32_t idx ) const { return eles_[idx]; }
    Typ& operator[] ( int32_t idx ) { return eles_[idx]; }
    int32_t size() const { return eles_.size(); };
private:
    std::vector<Typ> eles_;
};

The problem arises in the VecSum class definition which had been a template class already in the hardcoded double case and is now not recognized as being of the correct form for VecExn.

template <typename Typ, template <typename> typename Lhs, template <typename> typename Rhs>
class VecSum: public VecExn<Typ, VecSum<Typ, Lhs, Rhs> >  // ERROR: does not match the template parameter list for template parameter 'Exn'
{
public:
    VecSum( Lhs<Typ> const& lhs, Rhs<Typ> const& rhs ) : lhs_( lhs ), rhs_( rhs ) {}
    Typ operator[] ( int32_t idx ) const { return lhs_[idx] + rhs_[idx]; }
    int32_t size() const { return lhs_.size(); };
private:
    Lhs<Typ> const& lhs_;
    Rhs<Typ> const& rhs_;
};

How can I resolve this?

staerkHelmis

As pointed out by @super and @Jarod42 the solution is very simple:

Don't use a template template argument in the base class or the expression templates for operators but instead replace the return type of double operator[] by auto.

template <typename Exn>
class VecExn
{
public:
    auto operator[] ( int32_t idx ) const { return static_cast<Exn const&>( *this )[idx]; }
    int32_t size() const { return static_cast<Exn const&>( *this ).size(); }
};

template <typename Typ>
class Vec: public VecExn<Vec<Typ>>
{
public:
    Vec() {}
    Vec( std::initializer_list<Typ> iniLis ) : eles_( iniLis ) {  }
    template < typename Exn1 >
    Vec( VecExn<Exn1> const& exn ) : eles_( exn.size() )
    {
        for( int32_t idx = 0; idx < exn.size(); ++idx )
            eles_[idx] = exn[idx];
    }
    template < typename Exn1 >
    Vec& operator=( VecExn<Exn1> const& exn )
    {
        for( int32_t idx = 0; idx < exn.size(); ++idx )
            eles_[idx] = exn[idx];
        return *this;
    }

    Typ operator[] ( int32_t idx ) const { return eles_[idx]; }
    Typ& operator[] ( int32_t idx ) { return eles_[idx]; }
    int32_t size() const { return eles_.size(); };
private:
    std::vector<Typ> eles_;
};


template <typename Lhs, typename Rhs>
class VecSum: public VecExn<VecSum<Lhs, Rhs> >
{
public:
    VecSum( Lhs const& lhs, Rhs const& rhs ) : lhs_( lhs ), rhs_( rhs ) {}
    auto operator[] ( int32_t idx ) const { return lhs_[idx] + rhs_[idx]; }
    int32_t size() const { return lhs_.size(); };
private:
    Lhs const& lhs_;
    Rhs const& rhs_;
};

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How to make Derived class templated on Base class in CRTP

From Dev

How can I call the constructor of the derived class when using CRTP?

From Dev

Can I forward template arguments of a derived class to the base in CRTP?

From Dev

Can't use struct in derived templated class?

From Dev

CRTP with derived class overloading the method

From Dev

How can I friend a derived class function in the base class?

From Java

How to use aggregated initialization in derived class with CRTP pattern?

From Dev

Why can't I use alias from a base class in a derived class with templates?

From Dev

How can I implement a Singleton class that can be derived from in WPF?

From Dev

How can I implement a Singleton class that can be derived from in WPF?

From Dev

Iterate over different CRTP Derived class methods

From Dev

Accessing protected members of derived class with CRTP

From Dev

C++ CRTP constructor of derived class

From Dev

How can I find out which method of a derived class is not implemented?

From Dev

how can I obtain HWND of a class derived from QMainWindow

From Dev

How can I do constructor overloading in a derived class in TypeScript?

From Dev

How can I retrieve the derived class from a list of abstract classes?

From Dev

How can I "un-JsonIgnore" an attribute in a derived class?

From Dev

how can I obtain HWND of a class derived from QMainWindow

From Dev

How can I find out which method of a derived class is not implemented?

From Dev

How can I retrieve the derived class from a list of abstract classes?

From Dev

C++ How can I return an unknown derived class?

From Dev

How can I access a method defined with new keyword in a derived class

From Dev

Specialize member function of a templated derived class

From Java

Template deduction with derived templated class and smart pointers

From Dev

Specializing function template for templated derived class

From Dev

How do I make a derived class cloneable?

From Dev

can't invoke Base templated class's constructor from the derived class

From Dev

How can a derived class pointer to a base class object call methods of the derived class?

Related Related

  1. 1

    How to make Derived class templated on Base class in CRTP

  2. 2

    How can I call the constructor of the derived class when using CRTP?

  3. 3

    Can I forward template arguments of a derived class to the base in CRTP?

  4. 4

    Can't use struct in derived templated class?

  5. 5

    CRTP with derived class overloading the method

  6. 6

    How can I friend a derived class function in the base class?

  7. 7

    How to use aggregated initialization in derived class with CRTP pattern?

  8. 8

    Why can't I use alias from a base class in a derived class with templates?

  9. 9

    How can I implement a Singleton class that can be derived from in WPF?

  10. 10

    How can I implement a Singleton class that can be derived from in WPF?

  11. 11

    Iterate over different CRTP Derived class methods

  12. 12

    Accessing protected members of derived class with CRTP

  13. 13

    C++ CRTP constructor of derived class

  14. 14

    How can I find out which method of a derived class is not implemented?

  15. 15

    how can I obtain HWND of a class derived from QMainWindow

  16. 16

    How can I do constructor overloading in a derived class in TypeScript?

  17. 17

    How can I retrieve the derived class from a list of abstract classes?

  18. 18

    How can I "un-JsonIgnore" an attribute in a derived class?

  19. 19

    how can I obtain HWND of a class derived from QMainWindow

  20. 20

    How can I find out which method of a derived class is not implemented?

  21. 21

    How can I retrieve the derived class from a list of abstract classes?

  22. 22

    C++ How can I return an unknown derived class?

  23. 23

    How can I access a method defined with new keyword in a derived class

  24. 24

    Specialize member function of a templated derived class

  25. 25

    Template deduction with derived templated class and smart pointers

  26. 26

    Specializing function template for templated derived class

  27. 27

    How do I make a derived class cloneable?

  28. 28

    can't invoke Base templated class's constructor from the derived class

  29. 29

    How can a derived class pointer to a base class object call methods of the derived class?

HotTag

Archive