#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
,所有方法都依赖于S
和p
,这些方法都需要在普通类中执行两次一旦进入专业化阶段。有没有办法避免重复的代码?我看到了类似的问题:
Avoiding code duplication in a specialized template
但答案在我的案例中不起作用,因为我最终会得到p
的许多副本,在递归层次结构的每个级别都有一个副本。
答案 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;
};