C++0x initializer_list を使用して、std::array のようなコンテナー (組み込み C 配列の薄いラッパー) を実装することは可能ですか?
はい、まあ、ごまかす気がある限り。Mooing Duck が指摘しているように、コンパイラの実装者が許可しない限り、不正行為でさえありません。ただし、十分に近づけることはまだ可能です。初期化子リストと、ラッパーによって隠されている静的配列を使用することは可能です。
これは、個人用ツールボックス用に作成したコードです。重要なのは、配列であってもサイズを完全に無視し、プロバイダー コンテナーに処理させることです。この場合、initializer_list
誰が を介してサイズを提供できるstd::distance
ので、クライアント側のサイズの明示を回避できます (私が発明したばかりの用語のようです)。
これは「誰でも思いついた」種類のコードであるため、公開に「戻す」ことに問題はありません。実際、Freenode のチャンネルでニックネームを覚えていない専門家からアイデアを得た##c++
ので、認識は彼らのためだと思います。
*編集*編:
template <typename T> struct carray {
// typedefs for iterator. The best seems to be to use std::iterator<std::random_iterator_tag,T,int> here
...
template <size_t N>
explicit carray (T (&arr)[N])
: ax(arr), sx(N) {}
// note the linked article.
// This works *only* if the compiler implementor lets you.
carray (std::initializer_list<T> X)
: ax (X.begin()), sx(std::distance(X.begin(),X.end()) {}
// YMMV about the rest of the "rule of N":
// no copy constructor needed -- trivial
// no destructor needed -- data outscopes the wrapper
// no assignment operator needed -- trivial
// container functions, like begin(), end(), size()...
private:
T* ax;
size_t const sx;
};
C++0x モードでの使用法と宣言は非常に単純ですが (Fedora 15 の GCC 4.6 でテストしただけです)、上記の外部リンクに記載されている警告に従って動作するため、明らかに未定義の動作です:
using lpp::carray;
carray<short const> CS = {1, -7, 4, 188};
ただし、コンパイラの実装者が整数の initializer_list を静的配列として実装しない理由がわかりません。あなたの電話。
そのように機能するだけでなく、#ifdef
C++0x より前のモードで初期化子コンストラクターを邪魔にならないようにすることができれば、C++0x より前のモードで実際にこれを使用できます。データ配列を独自の変数として事前宣言する必要がありますが、元の意図に最も近いのは IMHO です (また、使用可能であり、スコープの問題などを引き起こさないという利点があります)。(上記のコンパイラと Debian Wheezy の GCC でもテスト済み):
using lpp::carray;
short data[]= {1, -7, 4, 188};
carray<short const> CS (data);
そこには!どこにも「サイズ」パラメータはありません!
初期化子リストが提供されていない場合は、サイズを指定するコンストラクターも提供する必要があります。
申し訳ありませんが、これは私が実装することを考えていない機能の 1 つです。問題は、外部ソース、おそらくアロケーターからメモリを「静的に」割り当てる方法です。ヘルパー functor を介して何らかの方法で実行できると仮定するとallocate
、コンストラクターは次のようになります。
explicit carray (size_t N)
: ax(allocate(N)), sx(N) {}
質問が多かれ少なかれ古いことがわかるので、このコードが役立つことを願っています。