类非类型模板参数上的c++成员函数模板专用化

c++ member function template specialization on class non-type template parameter

本文关键字:成员 c++ 函数模板 专用 类型 参数      更新时间:2024-09-22

从以下示例开始:

#include <cstdio>
template<int X, int Y>
struct C {
template<int Z> void bar() {printf("Generic %d/%dn",X,Y);}
void foo() {bar<Y>();}
};
int
main(int argc, char *argv[])
{
C<0,0> c0;
c0.foo();
C<0,1> c1;
c1.foo();
}

我现在想定义附加的";CCD_ 1";专门研究";Y";。特别是类似下面插入的行(对不起,我不知道如何突出显示它们(:

#include <cstdio>
template<int X, int Y>
struct C {
template<int Z> void bar() {printf("Generic %d/%dn",X,Z);}
template<> void bar<1>() {printf("Special %d/1n",X);}
void foo() {bar<Y>();}
};
template<int X> template<> C<X,2>::bar<2>() {printf("Special %d/2n",X);}
int
main(int argc, char *argv[])
{
C<0,0> c0;
c0.foo();
C<0,1> c1;
c1.foo();
}

遗憾的是,这两种方法似乎都不是有效的/compile(gcc/9.3.0,-std=c++11(。例如:

tempspec.cpp:94:12: error: explicit specialization in non-namespace scope ‘struct C<X, Y>’
94 |   template<> void bar<1>() {printf("Special %d/1n",X);}
|            ^
tempspec.cpp:94:26: error: template-id ‘bar<1>’ in declaration of primary template
94 |   template<> void bar<1>() {printf("Special %d/1n",X);}
|                          ^
tempspec.cpp:97:33: error: expected initializer before ‘<’ token
97 | template<int X> void C<X,2>::bar<2>() {printf("Special %d/2n",X);}
|                                 ^

我知道我不能部分专门化一个函数(这是我真正想做的(,但我认为我在这里是部分专门化结构,而完全专门化函数。

所以问题是,我如何定义";CCD_ 3";作为成员功能?

(至于为什么,假设"bar()"是模版计算,"Y"是模版的大小。基于"Y",我可能有针对特定大小优化的不同实现。(

至于原因,请说"条";是模版计算;Y";是模具的大小。基于";Y";我可能有针对特定大小优化的不同实现。

所以我的建议是:避免专业化,并在标记调度中使用重载。

一般情况下的一个模板bar()特殊情况下的一些非模板bar()

#include <iostream>
template <int X, int Y>
struct C
{
template <typename T>
void bar (T const &)
{ std::cout << "Generic " << X << '/' << Y << 'n'; }
void bar (std::integral_constant<int, 1> const &) 
{ std::cout << "Special " << X << '/' << 1 << 'n'; }
void bar (std::integral_constant<int, 2> const &) 
{ std::cout << "Special " << X << '/' << 2 << 'n'; }
void bar (std::integral_constant<int, 4> const &) 
{ std::cout << "Special " << X << '/' << 4 << 'n'; }
void foo ()
{ bar(std::integral_constant<int, Y>{}); }
};
int main ()
{
C<0,0>{}.foo();
C<0,1>{}.foo();
C<0,2>{}.foo();
C<0,3>{}.foo();
C<0,4>{}.foo();
C<0,5>{}.foo();
}

不允许直接做你想做的事。显式专门化要求为所有模板参数指定显式值。这意味着类模板参数和成员函数模板参数。例如,这将是合法的:

template<>
template<>
void C<1,1>::bar<1>() { printf("Special %d/1n",1); }

但是,如果您不使用template<>,那么您要么是在定义以前声明的成员,要么是在部分专门化领域,但由于函数重载和部分专门化之间的冲突,部分专门化只允许用于类模板和变量模板。

请注意,显式专门化不是模板(尽管有bar()0语法(。这就是为什么它不出现在类模板中很重要。

然而,这些类型的问题可以通过使用一个单独的类模板来解决,您可以部分专门化这个模板:

#include <cstdio>

template<int X, int Y> struct C;

template <int X, int Y, int Z>
struct CBar {
static void bar(C<X,Y> &) {
printf("Generic %d/%dn",X,Z);
}
};

template <int X, int Y>
struct CBar<X,Y,1> {
static void bar(C<X,Y> &) {
printf("Special %d/%dn",X,1);
}
};

template <int X>
struct CBar<X,2,2> {
static void bar(C<X,2> &) {
printf("Special %d/%dn",X,2);
}
};

template<int X, int Y>
struct C {
template<int Z> void bar() { CBar<X,Y,Z>::bar(*this); }
void foo() {bar<Y>();}
};

int main(int , char *[])
{
C<0,0> c0;
c0.foo();
C<0,1> c1;
c1.foo();
C<0,2> c2;
c2.foo();
}

程序标准输出

Generic 0/0
Special 0/1
Special 0/2