当模板完全专用时,不需要复制成员函数。例如,在以下代码中,foo()
仅写入一次。
#include <iostream>
template<int M>
class B
{
public:
void foo();
private:
void header();
};
template<int M>
void
B<M>::foo()
{
// specialized code:
header();
// generic code:
std::cout << "M = " << M << std::endl;
}
template<int M>
void
B<M>::header()
{
std::cout << "general foo()" << std::endl;
}
template<>
void
B<2>::header()
{
std::cout << "special foo()" << std::endl;
}
但是,对于部分特化,有必要复制类定义和所有成员函数。例如:
#include <iostream>
template<int M, int N>
class A
{
public:
void foo();
private:
void header();
};
template<int M, int N>
void
A<M, N>::foo()
{
// specialized code:
header();
// generic code:
std::cout << "M = " << M << ", N = " << N << std::endl;
}
template<int M, int N>
void
A<M, N>::header()
{
std::cout << "general foo()" << std::endl;
}
template<int N>
class A<2, N>
{
public:
void foo();
private:
void header();
};
template<int N>
void
A<2, N>::foo()
{
// specialized code:
header();
// generic code:
std::cout << "M = " << 2 << ", N = " << N << std::endl;
}
template<int N>
void
A<2, N>::header()
{
std::cout << "special foo()" << std::endl;
}
请注意,A<2, N>::foo()
是A<M, N>::foo()
的副本,其中2个被人工替换M
。
在模板部分专业化的上下文中如何避免此类代码重复?
答案 0 :(得分:2)
在这种情况下,我会让基类不知道模板参数&#39; N&#39;:
#include <iostream>
template<int M>
class ABase
{
protected:
void header();
};
template<int M>
void
ABase<M>::header()
{
std::cout << "general header()" << std::endl;
}
template<>
void ABase<2>::header()
{
std::cout << "special header()" << std::endl;
}
template<int M, int N>
class A : private ABase<M>
{
public:
void foo();
};
template<int M, int N>
void
A<M, N>::foo()
{
// specialized code:
this->header();
// generic code:
std::cout << "M = " << M << ", N = " << N << std::endl;
}
int main()
{
A<1,0> a1;
a1.foo();
A<2,0> a2;
a2.foo();
}
或者,您可以专门化整个基类。
答案 1 :(得分:1)
您可以将header
移动到一个单独的类中,只有部分专门化这个:
#include <iostream>
template <int M, int N>
struct Header
{
static void header()
{
std::cout << "general foo()" << std::endl;
}
};
template <int N>
struct Header<2, N>
{
static void header()
{
std::cout << "special foo()" << std::endl;
}
};
template<int M, int N>
struct A
{
void foo();
};
template<int M, int N>
void
A<M, N>::foo()
{
Header<M,N>::header();
std::cout << "M = " << M << ", N = " << N << std::endl;
}
int main()
{
A<1,1> a11;
a11.foo();
A<2,5> a25;
a25.foo();
}
<强>输出强>
general foo()
M = 1, N = 1
special foo()
M = 2, N = 5
答案 2 :(得分:1)
使用标签发送的强制性答案:
您可以创建一个重载的辅助函数;一个在M == 2
案例中被调用,另一个在M != 2
时被调用。这允许您避免创建模板化基类。我们需要做的就是将条件M == 2
转换为一种类型,我们将使用std::true_type
中的std::false_type
和<type_traits>
来执行该类型
template<int M, int N>
class A
{
public:
void foo();
private:
void header();
void foo_helper(std::true_type); // for M == 2 case
void foo_helper(std::false_type); // for M != 2 case
};
执行转换为类型(编译时检查):
template<int I>
struct is_2 : std::false_type{};
template<>
struct is_2<2> : std::true_type{};
你可以像这样打电话给他们:
template<int M, int N>
void
A<M, N>::foo()
{
foo_helper(typename is_2<M>::type{});
// specialized code:
header();
// generic code:
std::cout << "M = " << M << ", N = " << N << std::endl;
}
template<int M, int N>
void
A<M, N>::foo_helper(std::true_type)
{
std::cout << "Specialized code for M==2 case\n";
}
template<int M, int N>
void
A<M,N>::foo_helper(std::false_type)
{
std::cout << "M!=2 case\n";
}
如果你想避免需要创建一个概念,那么你可以在std::integral_constant
上重载,但是你会得到一些编译时模板膨胀(See Jarod42's answer here):
// inside void foo()
foo_helper(std::integral_constant<int, M>());
template<typename T>
void foo_helper(T) // for M != 2 case
{
std::cout << "M!=2 case\n";
}
void foo_helper(std::integral_constant<int, 2>) // for M == 2 case
{
std::cout << "Specialized code for M==2 case\n";
}
答案 3 :(得分:0)
感谢所有提供答案的人。
按照Vaughn Cato提供的链接并继续沿另一个链接转到this解决方案,该解决方案使用class C
end
p C.instance_methods
#=> [:module_meth, :nil?, :===, :=~, :!~,...
p Hash.instance_methods.grep(/module_meth/)
#=> [:module_meth]
p [].module_meth
#=> "module meth"
而非模板部分专精化。
为手头的问题实施它会产生:
std::enable_if