13.10 Overloading the parenthesis operator


https://www.learncpp.com/cpp-tutorial/overloading-the-parenthesis-operator/
これまで見たリロード演算子はparameterを決定することができたが、
まだ決まっていません.たとえば、演算子==では、常に2つのパラメータのみが処理されます.
!Operatorの場合、パラメータは1つのみ処理されます
Parenthesis演算子()の場合、タイプと数を決定できます.
二つのことを常に覚えなければならない.
第一に、カッコ演算子は常にメンバー関数によって実装される必要があります.
第二に、オブジェクト向けでないC++では、()オペレータは通常関数を呼び出すために使用されます.
クラスでoperator()という名前の関数のみを呼び出す

An example


次に例を示します
class Matrix
{
private:
    double data[4][4]{};
};
dataの場合、4 x 4のマトリクスです
subscript演算子の場合は1次元配列ですが、今回は2次元配列の場合、既存のsubscript演算子では十分ではありません.
しかし()演算子については、私たちが望むパラメータを得ることができます.
そこで,二次元マトリクスに近づくには以下の方法を用いる.
#include <cassert> // for assert()

class Matrix
{
private:
    double m_data[4][4]{};

public:
    double& operator()(int row, int col);
    double operator()(int row, int col) const; // for const objects
};

double& Matrix::operator()(int row, int col)
{
    assert(col >= 0 && col < 4);
    assert(row >= 0 && row < 4);

    return m_data[row][col];
}

double Matrix::operator()(int row, int col) const
{
    assert(col >= 0 && col < 4);
    assert(row >= 0 && row < 4);

    return m_data[row][col];
}
前述したように、演算子()を定義して2つのintパラメータを受け入れる
現在実際に使用されているのは以下の通りです.
#include <iostream>

int main()
{
    Matrix matrix;
    matrix(1, 2) = 4.5;
    std::cout << matrix(1, 2) << '\n';

    return 0;
}
parameterは一切受け付けなくてもご利用いただけます
#include <iostream>

int main()
{
    Matrix matrix{};
    matrix(1, 2) = 4.5;
    matrix(); // erase matrix
    std::cout << matrix(1, 2) << '\n';

    return 0;
}

Having fun with functors


Operator()は、通常、通信を実装するために使用されます.
関数のようにクラスを使用する
通常の関数と比較して,関数の利点はクラスベースであるため,member変数では
データを格納可能
ここでは簡単な通信例です
#include <iostream>

class Accumulator
{
private:
    int m_counter{ 0 };

public:
    int operator() (int i) { return (m_counter += i); }
};

int main()
{
    Accumulator acc{};
    std::cout << acc(10) << '\n'; // prints 10
    std::cout << acc(20) << '\n'; // prints 30

    return 0;
}
上のコードからaccというobjectを使うと関数のように見えます
しかし、acc objectのmember変数に値を格納して使用することがわかります.
これを見ると、normal関数でもstatic変数を使用できる理由を考えるかもしれません.しかしfunctionでは、instanceはグローバルに1つしか持てません.
したがって、静的変数は一度に1つしか使用できません.
ただしfunctorを使用すると、必要に応じて任意の数のinstanceを作成し、それぞれ分離した場合にobjectとmember変数を使用することができます.