7

I have a template<typename T> function that takes a const vector<T>&. In said function, I have vectors cbegin(), cend(), size(), and operator[]. As far as I understand it, both string and vector use contiguous space, so I was wondering if I could reuse the function for both data types in an elegant manner.

Can a std::string be reinterpreted as a std::vector of (the appropriate) char_type? If so, what would the limitations be?

4

7 に答える 7

14

型専用のテンプレートを作成し、ベクトルと文字列の両方が共有する、などの関数をconst T&使用すると、コードは両方の型で機能します。begin()end()

于 2015-10-08T21:41:22.620 に答える
7

STL の方法に進み、イテレータを使用します。開始する反復子と終了する反復子を受け入れます。ストリームのような非コンテナを含む、考えられるすべてのコンテナで動作します。

于 2015-10-08T21:44:57.323 に答える
6

レイアウトが同じになる保証はありませstringvector。理論的にはそうなる可能性がありますが、おそらく一般的な実装ではありません。したがって、これを安全に行うことはできません。より良い解決策については、ザンの回答を参照してください。

説明させてください:私が標準ライブラリの実装者であり、 std::string を実装することにした場合....

template ...
class basic_string {
public:
    ...
private:
    CharT* mData;
    size_t mSize;
};

std::vector のように実装することにします...

template ...
class vector {
public:
    ...
private:
    T* mEnd;
    T* mBegin;
};

データの末尾へのポインターをreinterpret_cast<string*>(&myVector)データの先頭へのポインターとして解釈し、データの先頭へのポインターをデータのサイズに解釈することになります。メンバー間のパディングが異なる場合、または余分なメンバーがある場合は、それよりもさらに奇妙で壊れたものになる可能性があります。

はい、これが機能する可能性があるためには、両方が連続したデータを保存する必要がありますが、それが機能するためには、実装間で同じにする必要があります。

于 2015-10-08T21:42:43.527 に答える
2

特定の char 型のインスタンスが格納されているメモリ内の連続領域にアクセスすることが重要な場合は、関数を次のように定義できます。

void myfunc(const CType *p, int size) {
     ...
}

それらがメモリ内で隣接している必要があると想定していることを明確にするため。

たとえば、ベクトルのコンテンツを渡すには、コードは単純です

myfunc(&myvect[0], myvect.size());

および文字列の場合

myfunc(mystr.data(), mystr.size());

また

myfunc(buffer, n);

配列の場合。

于 2015-10-08T21:48:20.023 に答える
1

現時点での質問の仕方は少し混乱しています。std::vector「ベクトルに適切な型の char 値が含まれている場合、型を型にキャストしstd::stringたり、その逆を行ったりしても安全ですか?」と尋ねるつもりなら、答えは次のとおりです。あなたが尋ねているなら:「それらが型である場合、char型の空でないシーケンスの連続したメモリにアクセスできますstd::vectorstd::string?」答えは、はい、できます(data()メンバー関数を使用)。

于 2015-10-09T07:57:30.373 に答える
1

std::vector を std::string に、またはその逆に直接型キャストすることはできません。しかし、STL コンテナーが提供する反復子を使用すると、ベクトルと文字列の両方を同じ方法で反復処理できます。また、関数が問題のコンテナーへのランダム アクセスを必要とする場合は、どちらでも機能します。

std::vector<char> str1 {'a', 'b', 'c'};
std::string str2 = "abc";

template<typename Iterator>
void iterator_function(Iterator begin, Iterator end)
{
  for(Iterator it = begin; it != end; ++it)
  {
    std::cout << *it << std::endl;
  }
}

iterator_function(str1.begin(), str1.end());
iterator_function(str2.begin(), str2.end());

最後の 2 つの関数呼び出しはどちらも同じものを出力します。

ここで、文字列またはベクトルに格納されている文字のみを解析する汎用バージョンを書きたい場合は、内部配列を反復するものを書くことができます。

void array_function(const char * array, unsigned length)
{
  for(unsigned i = 0; i < length; ++i)
  {
    std::cout << array[i] << std::endl;
  }
}

次のシナリオでは、どちらの関数も同じことを行います。

std::vector<char> str1 {'a', 'b', 'c'};
std::string str2 = "abc";

iterator_function(str1.begin(), str1.end());
iterator_function(str2.begin(), str2.end());
array_function(str1.data(), str1.size());
array_function(str2.data(), str2.size());

問題を解決するには常に複数の方法があります。利用可能なものに応じて、任意の数のソリューションが機能する可能性があります。両方を試して、どちらがアプリケーションに適しているかを確認してください。反復子の型がわからない場合は、char 型の配列反復が役立ちます。渡すテンプレート型が常にあることがわかっている場合は、テンプレート iterator メソッドの方が便利かもしれません。

于 2015-10-08T21:46:17.550 に答える