11

部分模板特化是 C++ 中泛型编程最重要的概念之一。例如:实现一个通用的交换函数:

template <typename T>
void swap(T &x, T &y) {
  const T tmp = x;
  y = x;
  x = tmp;
}

将其专门用于支持 O(1) 交换的向量:

template <typename T, class Alloc>
void swap(vector<T, Alloc> &x, vector<T, Alloc> &y) { x.swap(y); }

因此,当您在通用函数中调用 swap(x, y) 时,您始终可以获得最佳性能;

非常感谢,如果您可以在替代语言中发布等效的(或语言的部分专业化的规范示例,如果该语言不支持交换概念)。

编辑:所以看起来很多回答/评论的人真的不知道部分专业化是什么,并且通用交换示例似乎妨碍了某些人的理解。一个更一般的例子是:

template <typename T>
void foo(T x) { generic_foo(x); }

部分专业化将是:

template <typename T>
void foo(vector<T> x) { partially_specialized_algo_for_vector(x); }

一个完整的专业化将是:

void foo(vector<bool> bitmap) { special_algo_for_bitmap(bitmap); }

为什么这很重要?因为您可以在通用函数中调用 foo(anything) :

template <typename T>
void bar(T x) {
  // stuff...
  foo(x);
  // more stuff...
}

并在编译时获得最合适的实现。这是 C++ 以最小的性能损失实现抽象的一种方式。

希望它有助于澄清“部分专业化”的概念。在某种程度上,这就是 C++ 在不需要显式模式匹配语法(比如 Ocaml/F# 中的 match 关键字)的情况下进行类型模式匹配的方式,这有时会妨碍泛型编程。

4

6 回答 6

5

D支持偏特化:

(在上述链接中扫描“部分”)。

特别是第二个链接将为您提供模板专业化可以做什么的非常详细的细分,不仅在 D 中,在 C++ 中也是如此。

这是 D 的特定示例swapThing它应该打印出该类专用交换的消息。

import std.stdio;    // for writefln

// Class with swap method

class Thing(T)
{
public:

    this(T thing)
    {
        this.thing = thing;
    }

    // Implementation is the same as generic swap, but it will be called instead.
    void swap(Thing that)
    {
       const T tmp = this.thing;
       this.thing = that.thing;
       that.thing = tmp;
    }

public:

    T thing;
}


// Swap generic function

void swap(T)(ref T lhs, ref T rhs)
{
    writefln("Generic swap.");

    const T tmp = lhs;
    lhs = rhs;
    rhs = tmp;
}

void swap(T : Thing!(U))(ref T lhs, ref T rhs)
{
    writefln("Specialized swap method for Things.");

    lhs.swap(rhs);
}

// Test case

int main()
{
    auto v1 = new Thing!(int)(10);
    auto v2 = new Thing!(int)(20);

    assert (v1.thing == 10);
    assert (v2.thing == 20);
    swap(v1, v2);
    assert (v1.thing == 20);
    assert (v2.thing == 10);

    return 0;
}
于 2008-12-24T18:56:50.087 回答
1

I am afraid that C# does not support partial template specialization.

Partial template specialization means:

You have a base class with two or more templates (generics / type parameters). The type parameters would be <T, S>

In a derived (specialized) class you indicate the type of one of the type parameters. The type parameters could look like this <T, int>.

So when someone uses (instantiates an object of) the class where the last type parameter is an int, the derived class is used.

于 2008-12-19T08:09:33.457 回答
1

Haskell has overlapping instances as an extension:

class Sizable a where
  size :: a -> Int

instance Collection c => Sizable c where
  size = length . toList

is a function to find size of any collection, which can have more specific instances:

instance Sizable (Seq a) where
  size = Seq.length

See also Advanced Overlap on HaskellWiki.

于 2008-12-19T08:29:13.997 回答
0

实际上,您可以(不完全;见下文)使用扩展方法在 C# 中执行此操作:

public Count (this IEnumerable<T> seq) {
    int n = 0;
    foreach (T t in seq)
        n++;
    return n;
}

public Count (this T[] arr) {
    return arr.Length;
}

然后调用array.Count()将使用专用版本。“不完全”是因为分辨率取决于 的静态类型array,而不是运行时类型。即这将使用更通用的版本:

IEnumerable<int> array = SomethingThatReturnsAnArray();
return array.Count();
于 2008-12-19T08:54:15.020 回答
-1

C#:

void Swap<T>(ref T a, ref T b) {   
  var c = a;   
  a = b;   
  b = c;
}

I guess the (pure) Haskell-version would be:

swap :: a -> b -> (b,a)
swap a b = (b, a)
于 2008-12-19T07:44:12.493 回答
-3

Java 有泛型,它允许你做类似的事情。

于 2008-12-19T04:01:20.150 回答