我有一个基本模板:
template <class X> void f(X x) {}
现在我已经看到了两种专门化它的方法:
template <> void f<>(int x) {}
或者:
template <> void f<int>(int x) {}
gcc 会同时吃掉这两种变体,但不能同时吃掉这两种变体。
这两个专业是一样的吗?专门模板时,何时需要在第二个 <> 中指定类型?
我有一个基本模板:
template <class X> void f(X x) {}
现在我已经看到了两种专门化它的方法:
template <> void f<>(int x) {}
或者:
template <> void f<int>(int x) {}
gcc 会同时吃掉这两种变体,但不能同时吃掉这两种变体。
这两个专业是一样的吗?专门模板时,何时需要在第二个 <> 中指定类型?
两个专业是一样的。template<>
总是专门化一个现有的模板,而不是声明一个新的签名。如果从专业化参数类型中推导可以确定里面的内容<>
,那么您可以省略该部分。(如果有更多的模板重载,那么将这些东西排除在外可能是个坏主意。可能会不清楚哪个模板是专门化的。)
顺便说一句,专门化功能通常是个坏主意。重载解析将更喜欢非模板重载,并有效地隐藏您希望阻止的专业化。与其结合重载和专业化机制,不如坚持重载。
您的两个变体都执行相同的专业化。您还可以使用第三种变体
template <> void f(int x) {}
它还将专门用于X = int
. 它相当于您的第二个变体。
变体 withf<>
和 plainf
依赖于模板参数推导,而f<int>
变体显式指定模板参数。
<>
当模板参数推导不可能时,您可能需要显式指定类型。在其他情况下,您不必这样做。
例如,如果您的函数参数列表不依赖于模板参数X
,那么您别无选择,只能显式指定模板参数
template <typename X> void bar() {}
template <> void bar<int>() {}
以上编译。但是,如果您将专业化替换为
template <> void bar<>() {}
它将无法编译,因为编译器无法推断出模板参数。