48615


int main関数の部のコメント部のなのですが[暗黙的に宣言、削除された関数です]と  
エラーが出てしまい修正に困っています、ヘッダー部にoperator関数を用意しているので。何が間違えなのか検討もつきません、教えてもらえますでしょうか？初学者なので解説もお願いしたいです。参考書:新版明解c++中級編
visual studio 2017

[code]

    //////////////////////boolArray.h////boolへの明示的特殊化をしたクラス/////
    
    #ifndef ___Class_Template_Array_Bool
    #define ___Class_Template_Array_Bool
    #include <iostream>
    #include <limits>
    #include "Array.h"
    
    //===== 配列クラステンプレートArray（bool型への特殊化）=====//
    template<> class Array<bool> {
        typedef unsigned char BYTE;
        static const int CHAR_BITS = std::numeric_limits<unsigned char>::digits;
    
        int nelem;      // bool型配列の要素数
        int velem;      // bool型配列を格納するためのBYTE型配列の要素数
        BYTE *vec;      // BYTE型先頭要素へのポインタ
    
        // bool型sz個の要素の格納に必要なBYTE型配列の要素数
        static int size_of(int sz) { return (sz + CHAR_BITS - 1) / CHAR_BITS; }
    
    public:
    
            //=== ビットベクトル（バイト）中の１ビットへの参照を表すためのクラス ===//
            class BitOfByteRef {
                BYTE &vec;      // 参照先BYTE
                int idx;// 参照先BYTE中のビット番号
    
            public:
    
                BitOfByteRef(BYTE& r, int i) : vec(r), idx(i) { }       // コンストラクタ
    
                operator bool() const { return (vec >> idx) & 1U; }     // 真偽を取得
    
                BitOfByteRef& operator = (bool b) {// 真偽を設定
                    std::cout << "BitOfByteRef operator = \n";
    
                    if (b)
                        vec |= 1U << idx;
                    else
                        vec &= ~(1U << idx);
    
                    return *this;
                }
    
            };
    
            //----- 添字範囲エラー class -----//
            class IdxRngErr {
                const Array<bool>* ident;
                int index;
            public:
                IdxRngErr(const Array<bool>* p, int i) : ident(p), index(i) { }
    
                int Index() const { return index; }
            };
    
        //--- 明示的コンストラクタ ---//
        explicit Array(int sz, bool v = bool()) : nelem(sz), velem(size_of(sz)) {
            vec = new BYTE[velem];
    
            for (int i = 0; i < velem; i++) {   // 全要素を初期化
                vec[i] = v;
                std::cout << vec[i]<<'\n';//デバック
            }
        }
    
        //--- コピーコンストラクタ ---//
        Array(const Array& x) {
            if (&x == this) {                       // 初期化子が自分自身であれば…
                nelem = 0;
                vec = NULL;
            }
            else {
                nelem = x.nelem;                    // 要素数をxと同じにする
                velem = x.velem;                    // 要素数をxと同じにする
                vec = new BYTE[velem];              // 配列本体を確保
    
                for (int i = 0; i < velem; i++)     // 全要素をコピー
                    vec[i] = x.vec[i];
            }
        }
    
        //--- デストラクタ ---//
        ~Array() { delete[] vec; }
    
        //--- 要素数を返す ---//
        int size() const { return nelem; }
    
        //--- 代入演算子= ---//
        Array& operator = (const Array<bool>& x) {
            //std::cout << "=\n";
            if (&x != this) {                   // 代入元が自分自身でなければ…
                if (velem != x.velem) {         // 代入前後の要素数が異なれば…
                    delete[] vec;               // もともと確保していた領域を解放
                    velem = x.velem;            // 新しい要素数
                    vec = new BYTE[velem];      // 新たに領域を確保
                }
    
                nelem = x.nelem;                // 新しい要素数
    
                for (int i = 0; i < velem; i++) // 全要素をコピー
                    vec[i] = x.vec[i];
            }
            return *this;
        }
    
        //--- 添字演算子[] ---//
        BitOfByteRef operator[](int i) {
            if (i < 0 || i >= nelem)
                throw IdxRngErr(this, i);               // 添字範囲エラー送出
    
            return BitOfByteRef(vec[i / CHAR_BITS], (i & (CHAR_BITS - 1)));
        }
    
        //--- 添字演算子[] ---//
        bool operator[](int i) const {
            if (i < 0 || i >= nelem)
                throw IdxRngErr(this, i);               // 添字範囲エラー送出
    
            return (vec[i / CHAR_BITS] >> (i & (CHAR_BITS - 1)) & 1U) == 1;
        }
    
    };
    
    //--- Array<bool>型配列aの全要素を0または1で連続表示 ---//
    void print_Array_bool(const Array<bool>& a)
    {
        for (int i = 0; i < a.size(); i++)
            std::cout << (a[i] ? '1' : '0');
    
    }
    
    #endif
    
    /////////////////////int main関数部//////////////////////////////
    #include <iostream>
    #include "conio.h"
    #include "Array.h"
    #include "BoolArray.h"
    using namespace std;
    
    int main() {
    
        Array<bool> x(10);      // 全要素をfalseで初期化
        Array<bool> y(x);       // yはxのコピー（要素数が10で全要素がfalse）
        Array<bool> z(5);       // zの要素数は5だが
        z = y;                  // yが代入されるので要素数は10となる
    
    //  z[1] = y[3];///ここです。
        y[2] = true;
        z[3] = true;
    
        Array<bool> a(10);
    
        cout << boolalpha;
    
        try {
    
            for (int i = 0; i < x.size(); i++)
            {
                cout << "x[" << i << "] = " << x[i] << '\n';
            }
    
            std::cout << "\n\n";
    
            for (int i = 0; i < y.size(); i++)
            {
                cout << "y[" << i << "] = " << y[i] << '\n';
            }
    
            std::cout << "\n\n";
    
            for (int i = 0; i < z.size(); i++)
            {
                cout << "z[" << i << "] = " << z[i] << '\n';
            }
    
        }
        catch (Array<bool>::IdxRngErr &x) {
            cout << "添え字範囲エラー:";
    
            cout << x.Index();
    
            _getch();
            return 0;
        }
    
        cout << "x = ";  print_Array_bool(x);  cout << '\n';
        cout << "y = ";  print_Array_bool(y);  cout << '\n';
        cout << "z = ";  print_Array_bool(z);  cout << '\n';
    
        _getch();
        return 0;
    }
    
[/code]


CC BY-SA 4.0
2018-09-20T12:36:36.780
48597
2018-09-22T12:57:28.727
2018-09-21T08:30:02.527
76
question
c++
operator関数が機能しない？


Visual Studio 2013 コンソールプロジェクト on Win10  
では、コンパイルも実行もできました。  
ただし、

・「Array.h」が見つからなかったので、当該インクルードをコメント化、  
かつ、以下のコード様にclass Array を自前で用意しました。

[code]

    　template< typename T> class    Array {};
    
[/code]

以上から推測するに、Array.h に問題があるのかもしれません。  
「#include "Array.h"」行を右クリックしてファイルを開き、意図したものか調べてみてはどうでしょう。


CC BY-SA 4.0
2018-09-21T02:19:42.447
48608
2018-09-21T02:19:42.447
3793
48597
answer


`template <typename T> class Array;` を補って gcc-7.3.0@x86_64-cygwin で試したところ

>
[code]

>     depr.cpp:17:13: error: ambiguous overload for 'operator=' (operand types
> are 'Array<bool>::BitOfByteRef' and 'Array<bool>::BitOfByteRef')
>        z[1] = y[3];///ここです。
>     BoolArray.h:35:19: note: candidate: Array<bool>::BitOfByteRef&
> Array<bool>::BitOfByteRef::operator=(bool)
>     BoolArray.h:24:9: note: candidate: Array<bool>::BitOfByteRef&
> Array<bool>::BitOfByteRef::operator=(const Array<bool>::BitOfByteRef&)
> <deleted>
>     BoolArray.h:24:9: note: candidate: Array<bool>::BitOfByteRef&
> Array<bool>::BitOfByteRef::operator=(Array<bool>::BitOfByteRef&&) <deleted>
>  
[/code]

となりました。

で。エラーになっている原因は

  * コピーコンストラクタがコンパイラによって暗黙に作られる場合がある
  * `operator=` がコンパイラによって暗黙に作られる場合がある
  * ところがこの例では `BitOfByteRef::operator=` を明示しているので「作られない = deleted 」
  * 自前で作った `BitOfByteRef::operator=` が正しく呼べない  
（暗黙に作られるはずの `operator=` と曖昧になっている）

曖昧さがある以前に現コードはほとんど全く意味が無いです。現コードにおいて `z[1]` は `BitOfByteRef operator[] (int i)
{ ... }` を呼び出しています。この返却値はコピーされた `BitOfByteRef`
一時オブジェクト、つまり右辺値になっています。この右辺値に対して `operator=`
を呼ぼうとしていますが、一時オブジェクト（右辺値）に代入しても意味がないです（即時デストラクトされるため）

この `z[1]=y[3];` で何がしたいのか次第で直し方が違うわけですが、どうしたいですか？


CC BY-SA 4.0
2018-09-21T05:53:32.177
48614
2018-09-21T05:53:32.177
8589
48597
answer


直接の原因は、`Array<bool>::BitOfByteRef`型(以降、単に`BitOfByteRef`)が参照フィールド(`BYTE &
vec`)を持っているため、暗黙に定義される`operator=(const BitOfByteRef &)`メソッドが定義されないことが原因と思います。

ですので、`operator=(const BitOfByteRef &)を明示的に定義することでエラーが解消されると思います。

[code]

            // コード例
            BitOfByteRef & operator=(const BitOfByteRef & rhs) {
                return this->operator=(rhs.operator bool());
                // 多分、これでもOK.
                // return *this = static_cast<bool>(rhs);
            }
    
[/code]

* * *

補足です。順を追ってみてみると、

[code]

    z[3] = y[1];
    
[/code]

では、`z[3]`は`BitOfByteRef`型と評価されます。また、`y[1]`も`BitOfByteRef`型と評価されます。つまり、`BitOfByteRef`型同士の代入と見なされます。  
ここで、`BitOfByteRef`型は`operator=(const BitOfByteRef
&)`(代入演算子)のメンバメソッドを定義していないので、暗黙に定義されようとします。が、暗黙に定義されるメソッドでは、各メンバをコピーする処理にしようとするのですが、参照型変数自身は代入できないため、暗黙のメソッド定義は行わない(定義を禁止(`delete`))ようです。  
そのため、コンパイラは「暗黙的に宣言、削除された関数です」とエラーにしていると思います。

＃`std::vector`の`std::vector<bool>`特殊化でも同じように`std::vector<bool>::reference`の代入演算子を2種類(`bool`と`reference`)定義しているようです。


CC BY-SA 4.0
2018-09-21T07:33:35.753
48615
2018-09-22T12:57:28.727
2018-09-22T12:57:28.727
20098
20098
48597
answer