Recursively copy template inheritance code

#include <iostream>

template< class T, unsigned S >
struct my_iterator;

template< class T >
struct my_iterator< T, 1 >
{ 
    T* p;
};

template< class T, unsigned S >
struct my_iterator : my_iterator< T, S / 2 >
{
    static_assert ((S & (S - 1)) == 0, "S must be a power of 2");

    using my_iterator< T, S / 2 >::p;

    unsigned burp() {return (*p) + S;}
};

int main()
{
    int v = 10;

    my_iterator< int, 8 > a;
    a.p = &v;
    std::cout << a.burp() << std::endl;

    my_iterator< int, 4 >& b = a;
    std::cout << b.burp() << std::endl;

    my_iterator< int, 1 > c;
    c.p = &v;
    std::cout << c.burp() << std::endl; // error: no member named 'burp'

    return 0;
}

This will fix the error:

template< class T >
struct my_iterator< T, 1 >
{ 
    unsigned burp() {return (*p) + 1;}

    T* p;
};

but in my real code I have many methods, and not just burpthat, it all depends on Sand p, which should all be implemented twice, once in the general class and once in the specialization. Is there a way to avoid code duplication? I saw this similar question:

Prevent code duplication in a custom template

but the answer will not work in my case, because I will have many copies p, one at each level of the recursive hierarchy.

+4
source share
3 answers

, 1, , - 0...
my_iterator<T,1> - .

    template< class T, unsigned S >
    struct my_iterator;

    template< class T >
    struct my_iterator< T, 0 >
    { 
        T* p;

    };

    template< class T, unsigned S >
    struct my_iterator : my_iterator< T, S / 2 >
    {
        static_assert ((S & (S - 1)) == 0, "S must be a power of 2");

        using my_iterator< T, S / 2 >::p;

        unsigned burp() {return (*p) + S;}
    };
+3

- :

template <typename T> struct opt_ptr { T* p; };

// to be able to use std::conditional with non instantiated type.
template <typename T> struct identity { using type = T; };

template<typename T, unsigned S>
struct my_iterator :
    std::conditional<S == 1,
                     identity<opt_ptr<T>>,
                     identity<my_iterator<T, S / 2>>>::type::type
{
    static_assert ((S & (S - 1)) == 0, "S must be a power of 2");

    using opt_ptr<T>::p; // Note that you may use this->p to avoid this line

    unsigned burp() {return *p + S;}
    // Other methods using S and p.
};
+1

You can pass S to the base template and move the method there.

template< class T, unsigned S, unsigned N >
struct my_iterator;

template< class T, unsigned S >
struct my_iterator< T,S, 1 >
{  
    unsigned burp() {return (*p) + S;}

    T* p;
};

template< class T, unsigned S, unsigned N = S >
struct my_iterator : my_iterator< T, S, N / 2 >
{
    static_assert ((S & (S - 1)) == 0, "S must be a power of 2");

    using my_iterator< T,S, N / 2 >::p;

};
0
source

All Articles