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 Java

Template deduction with derived templated class and smart pointers

From Java

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

From Dev

how can I obtain HWND of a class derived from QMainWindow

From Dev

Specializing function template for templated derived class

From Dev

How to make Derived class templated on Base class in CRTP

From Dev

C++ CRTP constructor of derived class

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?

From Dev

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

From Dev

How do I make a derived class cloneable?

From Dev

Accessing protected members of derived class with CRTP

From Dev

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

From Dev

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

From Dev

Can't use struct in derived templated class?

From Dev

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

From Dev

CRTP with derived class overloading the method

From Dev

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

From Dev

Specialize member function of a templated derived class

From Dev

Iterate over different CRTP Derived class methods

From Dev

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

From Dev

how can I obtain HWND of a class derived from QMainWindow

From Dev

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

From Dev

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

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 friend a derived class function in the base class?

From Dev

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

From Dev

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

Related Related

  1. 1

    Template deduction with derived templated class and smart pointers

  2. 2

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

  3. 3

    how can I obtain HWND of a class derived from QMainWindow

  4. 4

    Specializing function template for templated derived class

  5. 5

    How to make Derived class templated on Base class in CRTP

  6. 6

    C++ CRTP constructor of derived class

  7. 7

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

  8. 8

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

  9. 9

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

  10. 10

    How do I make a derived class cloneable?

  11. 11

    Accessing protected members of derived class with CRTP

  12. 12

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

  13. 13

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

  14. 14

    Can't use struct in derived templated class?

  15. 15

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

  16. 16

    CRTP with derived class overloading the method

  17. 17

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

  18. 18

    Specialize member function of a templated derived class

  19. 19

    Iterate over different CRTP Derived class methods

  20. 20

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

  21. 21

    how can I obtain HWND of a class derived from QMainWindow

  22. 22

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

  23. 23

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

  24. 24

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

  25. 25

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

  26. 26

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

  27. 27

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

  28. 28

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

  29. 29

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

HotTag

Archive