递归模板继承代码重复

时间:2014-07-18 20:04:15

标签: c++ templates

#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;
}

这将解决错误:

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

    T* p;
};

但是在我的真实代码中,我有许多方法,而不仅仅是burp,所有方法都依赖于Sp,这些方法都需要在普通类中执行两次一旦进入专业化阶段。有没有办法避免重复的代码?我看到了类似的问题:

Avoiding code duplication in a specialized template

但答案在我的案例中不起作用,因为我最终会得到p的许多副本,在递归层次结构的每个级别都有一个副本。

3 个答案:

答案 0 :(得分:3)

另一个选项,如果您希望仍然使用递归停止值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;}
    };

答案 1 :(得分:1)

另一种方法是在其他结构中移动特定的东西:

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.
};

答案 2 :(得分:0)

您可以将S传递给基本模板,然后将方法移动到那里。

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;

};