8

有模板类List。

template <typename Point>
class List
{


    public:
          template <const unsigned short N>
          void load ( const char *file);
          ...
};

template <typename Point>
template <const unsigned short N>
void List <Point>::load ( const char *file)
}

如何专门化 N=2 的方法负载?此代码无效...

template <typename Point>
void List <Point> <2>::load ( const char *file)
{
}

而且这段代码也不起作用。

template <typename Point>
void List <Point> ::load <2> ( const char *file )
{ 
}

Error 3 error C2768: 'List<Point>::load' : illegal use of explicit template arguments 66. 
Error 5 error C2244: 'List<Point>::load' : unable to match function definition to an existing declaration 66

编译器 g++:

template <typename Point>
template <>
void List <Point> ::load <2> ( const char *file )
{
}

error: explicit specialization in non-namespace scope `class List<>'
error: enclosing class templates are not explicitly specialized
error: default arguments are only permitted for function parameters
error: `load' is not a function template
error: invalid function declaration
4

3 回答 3

9

事实证明,C++ 规范中有一条规定明确禁止特化嵌套在模板类中的模板类或函数,除非您也明确地特化外部模板。Visual Studio 不强制执行此规则,因此会与前面的示例混淆,但 g++ 肯定会执行。

如果您想专门化模板,您的选择将是也专门化外部模板,或者通过将方法分派到基于模板参数的两个不同实现之一来以某种方式伪造专门化的行为。我知道,这些都不是很令人满意,但不幸的是,该语言在某些模板角落设计得很奇怪。:-(

可以模拟显式特化行为的一种方法是使用一种称为标记调度的技术。我们的想法是,我们将制作一个非常简单的结构,如下所示:

template <unsigned short N> struct Box {};

这种类型是完全空的。它并不意味着直接使用,而只是将整数嵌入到类型系统中的一种方式。特别Box<3>是,与Box<4>等不同。

接下来,在您的列表类中,定义两个如下所示的函数,最好标记为私有:

template <unsigned short N>
    void doLoad(const char* file, Box<N>);
void doLoad(const char* file, Box<2>);

这两个函数是彼此的重载,只能通过它们的最终参数来区分,Box<N>在模板情况下是 a Box<2>,在非模板情况下是 a 。请注意,参数没有名称。这是一个随意的决定,但由于我们不打算实际读取参数,所以我们不需要它们。这些函数背后的直觉是,第一个函数将是“包罗万象”的实现,适用于N除 2 之外的任何函数。第二个版本将包含在N == 2.

最后,实现load如下:

template <typename Point>
    template <unsigned short N>
void List<Point>::load(const char* file) {
    doLoad(file, Box<N>());
}

这是如何运作的?这个函数接受一个参数,然后调用doLoad转发该参数作为第一个参数,并传递一个临时参数Box<N>作为第二个参数。如果N不是两个,那么这是对模板版本的调用doLoad,它是包罗万象的处理程序。另一方面,如果N是 2,那么这将调用 的非模板版本doLoad,因为在重载决议期间非模板函数优先于模板函数。

简而言之,实现load只是成为一个蹦床,将您转发到两个实现中的正确位置。然后,您可以将逻辑放入适当的doLoad函数中以获得您想要的行为。

希望这可以帮助!

于 2011-02-09T22:02:16.377 回答
1

编辑:好的,所以我用内联函数定义重写了你的类,这绝对有效:

template <typename Point>
class List
{
public:
    template <const unsigned short N>
    void load( const char *file){
    }

    template<>
    void load<2>(const char* file){
    }
};
于 2011-02-09T11:29:46.260 回答
1

如果不专门化类模板,就无法专门化成员模板。

我也想知道 N 的含义是什么,因为它没有在函数参数中使用?

于 2011-02-09T22:03:18.090 回答