2011-01-04 9 views
4

私たちのクラスの中には、テンプレートがクラスの振る舞いをカスタマイズできるようになっていて、文字列クラスの例がありました。 「a」と「z」、「b」と「y」、「c」と「x」を同じように扱うことができます。 Similary 'A'と 'Z' sameなどカスタム動作の文字列クラスを実装する

"abc" == "zyx"は真です。
"Abc" == "zyx"は偽です。
「ABC == 『ZYX』は本当です。

など

どのように我々は、テンプレートを使用して、このような文字列クラスを実装することができ、私は、このような文字列クラスを実装することを考えていましたが、私はそうすることはできませんよ

。?
+1

私もC++に新たなんだけど、私はこれはとは何かを持っていると思いますキャラクターの特性。 – dreamlax

答えて

3

非常にトリッキーです。のみ当量(再定義)動作しません:あなたはあなた自身の特性クラスを記述する必要があるのは、特にあなたはchar_traits<>クラステンプレートからそれを導出し、EQ()は()機能(比較注を再定義する必要がありますのcompare()の再定義に変更はありませんが、そのように派生クラスに書く必要があります)。この特性クラスはsequence_traitsで、カスタム文字列はsequenceとなります。結局のところ、文字列は一連の文字です!

注:alphabets[i] == alphabets[25-i]は同じものとして扱われることをあなたの投稿から理解しています。つまり、最初の文字と最後の文字は同じです、2番目の文字と2番目の最後の文字は同じです。

struct sequence_traits : char_traits<char> 
{ 
    //'a' and 'z' are equal 
    //'b' and 'y' are equal 
    //'c' and 'x' are equal, and so on. 
    //that implies, 'a' + 'z' == 'b' + 'y' == 'c' + 'x' == 'd' + 'w == so on 
    //same for upper cases! 
    static bool eq(const char& left, const char& right) 
    { 
     return (left == right) || (left + right == 'a' + 'z') || (left + right == 'A' + 'Z') ; 
    } 
    static int compare(const char *first1, const char *first2, size_t count) 
    { 
     for (; 0 < count; --count, ++first1, ++first2) 
      if (!eq(*first1, *first2)) 
       return (lt(*first1, *first2) ? -1 : +1); 
     return (0); 
    } 
}; 

そして、あなたは簡単に使用するため、このtypedefを行うことができます。

typedef basic_string<char, sequence_traits> sequence; 

あなたは完了です。今すぐsequenceを使用できます。:-)

の作業例:http://www.ideone.com/ByBRV


それは具体的にどのように動作するかを知るためにこの記事を読む:http://www.gotw.ca/gotw/029.htm

+0

私はC++については分かりませんが、Cでは、アンダースコアと大文字(つまり_Leftと_Right)で始まる識別子は予約されており、それらを使用すると未定義の動作になります。 – dreamlax

+0

@dreamlax:誰がそれを言ったの? – Nawaz

+2

@Nawaz:C++標準では、§17.4.3.1.2はアンダースコアに関する予約済み識別子を定義し、§17.4.3.1パラグラフ3は予約済み識別子を使用する動作を定義します。 – dreamlax

2

char_traitsタイプを見たいと思うでしょう。これは、実用的な文字列タイプを得るためにbasic_stringで使用できる1種類の特性クラスの例です。独自の特性クラスを定義すると、次のようなカスタム文字列を作成します。

class CustomTraits { ... }; 
typedef basic_string<char, CustomTraits> CustomString; 

これで、CustomTraitsで定義された特性が、文字列の仕組みを決定するために使用されます。

あなたはこのような何か行うことができ、言っていた何の線に沿って一例として:今

class CustomTraits: public char_traits<char> { 
public: 
    /* Redefine equality to compare 'a' and 'z' equal. */ 
    static bool eq(char one, char two) { 
     return one == two || (one == 'a' && two == 'z' || one == 'z' && two == 'a'); 
    } 
}; 
typedef basic_string<char, CustomTraits> StringWithAAndZEqual; 

を、あなたは新しいタイプを使用することができますし、クラスが「A」と「Z」を扱います同じように。

+0

@templatetyepdef:これは彼が望むものではないと思います。これは 'a'と 'x'のみを等価的に扱いますが、 'b'や 'y'、 'c'、 'x'などの他のすべてのペアを扱うわけではありません。 'アルファベット[i] ==アルファベット[25-i]'は同じものとして扱われなければならないと思います。つまり、最初の文字と最後の文字は同じです、2番目の文字と2番目の最後の文字は同じです。 – Nawaz

+1

これは機能しません。それは 'b'と 'y'などのペアではなく 'a'と 'z'のために働く。 –

+1

私の謝罪 - 私は質問を誤解しました。しかし、これは主に概念の証明でした。他にもいくつか欠けているものがあります(lt、compareなど) – templatetypedef

2

あなたのカスタムchar_traitsを作り、それとstd::basic_stringをインスタンス化します。

+0

''= 'の演算子で異なる' 'char_traits''を持っていれば、2つのstd :: basic_stringを比較できますか? – dreamlax

+1

素朴ではありません。 'my_string'がカスタム文字列のインスタンスである場合、' my_string == a_std_string.c_str() 'のようなことをする必要があります。ストリームでストリームを使用する場合も同様です。おそらく 'std :: basic_string <> :: c_str()'を使う必要があります。 – wilhelmtell

関連する問題