专业功能模板与功能重载与类专业化

Tim*_*imW 7 c++ templates

根据Herb Sutter的这篇文章,我们应该总是选择Class Specializing over Function Overload,而不是专门的功能模板.

原因是

  • 专业化不会超载.重载分辨率仅选择基本模板(或非模板函数,如果有的话).只有在确定要选择哪个基本模板并且锁定了该选项之后,编译器才会查看是否恰好可以使用该模板的合适专用,如果是,则将使用专门化.
  • 我们不能专门的功能模板.

我必须承认,在我阅读这篇文章之前,我曾几次撞到墙上.他为什么不选择我的专业功能...
阅读完文章之后我再也没有使用过专业功能模板.

例:

template <class T> void foo( T t);
Run Code Online (Sandbox Code Playgroud)

我们应该像这样编写foo,这样我们就可以使用类模板而不是函数专用来专门化它.

template<class T> 
struct FooImpl;

template <class T> void foo( T t) {
    FooImpl<T>::foo(t);
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以对模板进行特殊处理,而不必担心过载规则,我们甚至可以将模板专门化为这样的模板:

template<class U, class V> 
struct FooImpl< QMap< U, V > >;
Run Code Online (Sandbox Code Playgroud)


这是个问题.

StackOverflow成员似乎更喜欢专业功能模板?
为什么?因为专业功能模板比过载解决方案和类专业化获得了更多的赞成.
凭借我目前所获得的信息,我发现它有悖常理,因为我知道我能说得对,但我知道跟在我身后的人会碰壁.

已经有一些GOTWCA文章的链接,所以你必须阅读这篇文章.这意味着upvoters必须有一些额外的信息,请站起来赐教.

Ric*_*den 4

仅当函数也重载时,显式专门化函数模板的问题才会出现:

template <typename T> void foo (T*);   // #1

template <typename T> void foo (T);    // #2
template <> void foo<int*> (int*);

int main () {
  int * i;
  foo (i);  // Calls #1 not specialization of #2
}
Run Code Online (Sandbox Code Playgroud)

如果没有 #1 重载,代码将按预期工作。然而,一开始没有重载的函数可能会随着代码的维护而添加重载。

这是其中一个例子,虽然我不想这么说,但 C++ 有太多方法可以做同样的事情。就个人而言,如果您发现需要专门化函数模板,那么我喜欢建议的模式就我个人而言,如果您发现需要专门化一个函数模板,那么我喜欢TimW在针对 Neil Butterworth 的答案的评论中,即。最好通过让当前函数分派它调用专门的类模板来做到这一点:

template <typename T> class DoFoo {
    static void do (T) { /* default behaviour */ }
};
template <> class DoFoo<int*> {
    static void do (int*) { /* int * behaviour */ }
};

template <typename T> void foo (T t)
{
  DoFoo<T>::do (t);
}
Run Code Online (Sandbox Code Playgroud)

如果“foo”被重载,那么至少开发人员更清楚该函数不会被调用,即。开发人员无需成为标准专家即可了解专业化规则如何与重载解析交互。

然而,最终编译器生成的代码将是相同的,这纯粹是开发人员的代码理解问题。

  • 我认为标准说得对:“在编写专业化时,要小心它的位置;否则使其编译将是一次考验,以至于点燃它的自焚。” 于 14.7.3/7 :) (3认同)