以前は、非 const から const への一方向変換を可能にする変換コンストラクターを使用して、構造体 (スマート ポインター、イテレーターなど) のようなポインターを記述していました。このスタイルは、const/non-const バージョンのコードの重複を防ぎます。例えば
template<class T>
struct ptr_like
{
using self_type = ptr_like<T>;
using nonconst_self = ptr_like<remove_const<T>>;
ptr_like() : ptr_(){}
//a friendship may be needed to access private member
ptr_like(nonconst_self const& rhs) : ptr_(rhs.ptr_){//implementation} 1)
//ptr_like(ptr_like const& rhs) = default; 2)
T* ptr_;//exposition only
};
ptr_like<int> x1,x2 = x1;//converting constructor
ptr_like<int const> x3,x4 = x3;//default constructor
//ptr_like<int> x5 = x3; //error as intended
ptr_like<int const> x6 = x1;//converting constructor, allowed conversion.
ただし、c++11 ではに対してis_trivially_copy_constructible
false であるのに対しptr_like<T>
、 に対して true であるためptr_like<T const>
、実際には、クラスのメンバー変数として使用するptr_like<T>
と、デフォルトの移動コンストラクターが削除されます (自明でないコピー コンストラクターがあり、移動コンストラクターが使用できないため)。ptr_like<T const>
自明なコピーコンストラクターがあるため、クラスのメンバーとして使用します。例えば
struct holder
{
ptr_like<int> p;//(3
holder(holder const&) = delete;
holder(holder&&) = default;
};
is_move_constructible<holder>() == false
std::vector<holder> v;
holder h;
v.push_back(std::move(h)); //this fails as no move constructor possible.
(2のように)にデフォルトのコピーコンストラクターを提供することptr_like
も役に立たない.ptr_like<T>
boost::circular_buffer<T>::iterator
この効果は、クラスに格納するとそのクラスの移動コンストラクターが無効になる多くのブースト クラス (例: ) で見られます。さらに、コピーコンストラクターが削除されていない場合、サイレントにコピーします。
では、問題は、c++11 で重複コードを使用してポインターのようなクラスを作成する最良の方法は何ですか? (補助的な質問として、メンバー変数に自明でないコピー コンストラクターがある場合にクラスのムーブ コンストラクターが無効になる理由を探しています)