在C++中什么时候需要或想要“显式专用化”?

uinbv5nw  于 2023-01-15  发布在  其他
关注(0)|答案(4)|浏览(213)

我在阅读
初级C++〉函数历险〉模板〉显式特化。
为了说明显式专门化的原因/用途,下面举例说明一个案例:
考虑一个可以交换任何类型(int, double, struct等)的交换模板函数
但是有一个特定的struct job,您只想交换其中的两个成员,而让其余成员保持原样。您将需要一个不同的定义,因此您必须进行显式特化。
在同一节中有这样一段话:
专门化会覆盖常规模板,而非模板函数会覆盖这两者。
为什么不为这种用途创建一个常规函数呢?然后常规/非模板将覆盖模板,不是吗?
如果我的解决方案是正确的,那么什么是显式特化的好例子?

3b6akqbq

3b6akqbq1#

显式专门化的一个用例是避免在实际template函数发生某些更改时跳过常规函数。要了解此内容,请参阅以下示例:

template<typename T1, typename T2>
void foo(T1 o1, T2 o2)  // template function
{}
void foo(int o1, int o2) // regular function overloaded
{}

到目前为止还不错,但过了一段时间,你必须改变template<> foo()的定义

template<typename T1, typename T2, typename T3> // new parameter added
void foo(T1 o1, T2 o2, T3 o3)  // template function
{}

您相应地更改了对foo()的所有调用,但是您错过/弄乱了更改常规重载函数foo()。然后,这是一个 * 灾难 *!因为编译会进行得很好,常规调用会默默地template<> foo()替换,这是不希望的。
现在,如果有明确的专业化,

template<>
void foo(int o1, int o2) // explicit specialization
{}

那么该函数将由于 * 不匹配的参数 * 而给予编译错误,并提醒您相应的更改。
另一个用法或(不同之处)是显式专用化函数可以包含在头文件中,而不必考虑多个符号链接错误。注意,显式专用化也有它自己的缺点,但我已经演示了它的好的一面。

ryevplcw

ryevplcw2#

为什么不直接做一个(常规)函数来做这个用途呢?然后常规/非模板将覆盖模板?
当然,如果你觉得合适的话,你可以使用常规函数重载代替显式函数模板专用化。但是如果你显式地使用函数模板(通过指定模板参数),常规函数重载将不会被使用。

    • 示例:**

您有函数模板:

template< class T >
void foo( T& x, const T& y )
{
...
}

如果指定函数重载:

void foo( double& x, const double& y )
{
....
}

代码如下:

template< class T >
void some_function( T& x )
{
    T y;
    ......
    foo<T>( x, y );
}

函数重载void foo( double& x, const double& y )将永远不会被使用。
但如果指定函数模板专用化

template<>
void foo<double>( double& x, const double& y )
{
....
}

那么some_function将使用您的专门化,如果您调用

double x;

some_function(x);

某个地方。

sf6xfgos

sf6xfgos3#

标准函数可以是特殊化的,但不能重载,这只是一个例子,另一个例子是类型是不可推导的,而你已经有了用显式模板参数调用它们的代码,那么你的重载就没有价值了。

d8tt03nd

d8tt03nd4#

另一种用法是将模板函数的特殊情况标记为不可调用。

template<typename T>
void processPointer(T* ptr);
template<>
void processPointer<void>(void*) = delete;
template<>
void processPointer<char>(char*) = delete;

(From* 有效的现代C++*)

相关问题