rainit2006 / C-Program

C# Program knowledge
0 stars 0 forks source link

Template类 和Generic #5

Open rainit2006 opened 7 years ago

rainit2006 commented 7 years ago

http://www.cnblogs.com/gw811/archive/2012/10/25/2738929.html 使用模板的目的就是能够让程序员编写与类型无关的代码。

函数模板的格式:

template <class 形参名,class 形参名,......> 返回类型 函数名(参数列表)
   {
      函数体
   }

类模板的格式为:

template<class  形参名,class 形参名,…>   class 类名
    { ... };

例子:     template class A{ public: T a; T b; T hy(T c, T &d); }; 在类A中声明了两个类型为T的成员变量a和b,还声明了一个返回类型为T带两个参数类型为T的函数hy。


template <typename T>
class Stack
{
public:
    void Push(T value);
    T Pop();
    bool IsEmpty();

private:
    std::vector<T> stack_;
};

インスタンス化します。
Stack<int> int_stack;
Stack<string> string_stack;

「特殊化」:テンプレートパラメータ対して具体的な型を特定する事。 部分的な特殊化は、元となる汎用なテンプレート引数のうちの、一部だけを特殊化する方法

template <typename KEY, VALUE>
class Set
{
    // 共通の処理
    bool Insert(KEY key, VALUE value);
};

template <typename VALUE>
class Set<int, VALUE>
{
    // Set<int, VALUE>で特殊化された際の特別処理
    bool Insert(int key, VALUE value);
};
rainit2006 commented 7 years ago

Generic http://ufcpp.net/study/csharp/sp2_generics.html Genericの制約条件 where T : struct 型Tは「値型」である
where T : class 型Tは「参照型」である
where T : new() 引数なしのコンストラクタを持つ。他の制約条件と同時に課す場合には、一番最後に指定する必要がある。
where T : [base class] 型Tは[base class]で指定された型を継承する。
where T : [interface] 型Tは[interface]で指定されたインターフェースを実装する。

例:要求Type必须继承了IComparable接口。

static Type Max<Type>(Type a, Type b)  where Type : IComparable
{
  // ↑この制約条件のお陰で、
  // ↓Type 型 は CompareTo を持っているというのが分かる。
  return a.CompareTo(b) > 0 ? a : b;
}
rainit2006 commented 6 years ago

C++ テンプレートと C# ジェネリックの違い 構文レベルでは、C# ジェネリックの場合、パラメーター化された型の取り扱いが単純であり、C++ テンプレートのような複雑さがありません。 さらに、C++ テンプレートで提供されるすべての機能が、C# でも提供されるわけではありません。 実装レベルでは、C# ジェネリック型の代入は実行時に行われ、その結果、インスタンス化されたオブジェクトのジェネリック型情報が保存されるという点が最も大きな違いです。

C# は、明示的な特殊化 (特定の型のテンプレートのカスタム実装) をサポートしません。 C# は、部分的な特殊化 (型引数のサブセットのカスタム実装) をサポートしません。 C# では、型パラメーターをジェネリック型の基底クラスとして使用できません。

https://stackoverflow.com/questions/31693/what-are-the-differences-between-generics-in-c-sharp-and-java-and-templates-i Both C# and Java produce output which is designed for virtual machines. If you write some code which has a Person class in it, in both cases some information about a Person class will go into the .dll or .class file, and the JVM/CLR will do stuff with this.

C++ produces raw x86 binary code. Everything is not an object, and there's no underlying virtual machine which needs to know about a Person class. There's no boxing or unboxing, and functions don't have to belong to classes, or indeed anything.

Because of this, the C++ compiler places no restrictions on what you can do with templates - basically any code you could write manually, you can get templates to write for you. The most obvious example is adding things:

In C# and Java, the generics system needs to know what methods are available for a class, and it needs to pass this down to the virtual machine. The only way to tell it this is by either hard-coding the actual class in, or using interfaces. For example:

string addNames( T first, T second ) { return first.Name() + second.Name(); } That code won't compile in C# or Java, because it doesn't know that the type T actually provides a method called Name(). You have to tell it - in C# like this:

interface IHasName{ string Name(); }; string addNames( T first, T second ) where T : IHasName { .... } And then you have to make sure the things you pass to addNames implement the IHasName interface and so on. The java syntax is different (), but it suffers from the same problems.

The 'classic' case for this problem is trying to write a function which does this

string addNames( T first, T second ) { return first + second; } You can't actually write this code because there are no ways to declare an interface with the + method in it. You fail.

C++ suffers from none of these problems. The compiler doesn't care about passing types down to any VM's - if both your objects have a .Name() function, it will compile. If they don't, it won't. Simple.