web-dev-qa-db-ja.com

C ++で呼び出し可能なオブジェクトとは何ですか?

私は現在、ブーストスレッドを研究しています。そして、スレッドクラスには呼び出し可能なオブジェクトを受け入れるコンストラクターがあることに気付きました。呼び出し可能なオブジェクトとは何ですか?

class CallableClass
{
private:
    // Number of iterations
    int m_iterations;

public:

    // Default constructor
    CallableClass()
    {
        m_iterations=10;
    }

    // Constructor with number of iterations
    CallableClass(int iterations)
    {
        m_iterations=iterations;
    }

    // Copy constructor
    CallableClass(const CallableClass& source)
    {
        m_iterations=source.m_iterations;
    }

    // Destructor
    ~CallableClass()
    {
    }

    // Assignment operator
    CallableClass& operator = (const CallableClass& source)
    {
        m_iterations=source.m_iterations;
        return *this;
    }

    // Static function called by thread
    static void StaticFunction()
    {
        for (int i=0; i < 10; i++)  // Hard-coded upper limit
        {
            cout<<i<<"Do something in parallel (Static function)."<<endl;
            boost::this_thread::yield(); // 'yield' discussed in section 18.6
        }
    }

    // Operator() called by the thread
    void operator () ()
    {
        for (int i=0; i<m_iterations; i++)
        {
            cout<<i<<" - Do something in parallel (operator() )."<<endl;
            boost::this_thread::yield(); // 'yield' discussed in section 18.6
        }
    }

};

これはどのようにして呼び出し可能なオブジェクトになりますか?演算子がオーバーロードされているのか、コンストラクターなどが原因ですか?

19
Xegara

呼び出し可能オブジェクトは、構文object()またはobject(args)を使用して関数のように呼び出すことができるものです。つまり、関数ポインタ、またはoperator()をオーバーロードするクラスタイプのオブジェクトです。

クラス内のoperator()のオーバーロードにより、呼び出し可能になります。

17
Mike Seymour

ここには2つのステップがあります。 C++標準では、「関数オブジェクト」は、括弧で囲まれた引数リストの左側に表示できるオブジェクトです。つまり、関数へのポインタ、または型に1つ以上のoperator()sがあるオブジェクトです。 。 「呼び出し可能オブジェクト」という用語はより広義です。メンバーへのポインターも含まれます(通常の関数呼び出し構文では呼び出すことができません)。呼び出し可能なオブジェクトは、std::bindなどに渡すことができるものです。20.8.1[func.def]および20.8 [function.objects]/1を参照してください。

5
Pete Becker

少なくともオーバーロードされたoperator()を持つオブジェクトは 呼び出し可能なオブジェクト であり、その演算子とそのオブジェクトをlike関数の呼び出し:

CallableClass obj;
obj();
4
masoud

呼び出し可能オブジェクトは、operator()がオーバーロードされたクラスのオブジェクトインスタンスです。

struct Functor {
    ret_t operator()();
    // ...
}

Functor func;  // func is a callable object

または逆参照関数ポインター:

ret_t func() {
   // ...
}

func;  // func converts to a callable object
2
Paul Evans

C++ 17以降、Callableオブジェクトは実際には標準で定義されています。詳細については、 https://en.cppreference.com/w/cpp/named_req/Callable を参照してください。

2
Carlo Wood

C++ 11では、呼び出し可能な要素は次のいずれかになります。

  • 関数ポインタ、
  • メンバー関数ポインタ(前のものとは異なりますので、チェックしてください ここ
  • ファンクタークラス(operator()が実装されているクラス)のオブジェクト、
  • 匿名関数(ラムダ)、
  • または、 std :: function オブジェクトでラップされた上記の要素のいずれか。

これは、前述の呼び出し可能な要素のそれぞれを使用して、std :: threadを起動できることを意味します。次のサンプルコードを見てください。

std::vector<int> v{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };

int func()
{
   return std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
}

class A
{
public:
   int mem_func() 
   { 
      return std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
   }
};

class B
{
public:
   int operator()()
   {
      return std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
   }
};

auto lambda = []() { return std::accumulate(v.begin(), v.end(), 1, std::multiplies<int>()); };


void main()
{
   A a;
   B b;

   std::function<int()> f1 = &func;
   std::function<int()> f2 = std::bind(&A::mem_func, &a);
   std::function<int()> f3 = std::bind(&B::operator(), &b);
   std::function<int()> f4 = lambda;

   std::thread t1 = std::thread(func);
   std::thread t2 = std::thread(&A::mem_func, a);
   std::thread t3 = std::thread(&B::operator(), b);
   std::thread t4 = std::thread(lambda);

   std::thread t5 = std::thread(f1);
   std::thread t6 = std::thread(f2);
   std::thread t7 = std::thread(f3);
   std::thread t8 = std::thread(f4);

   t1.join();
   t2.join();
   t3.join();
   t4.join();
   t5.join();
   t6.join();
   t7.join();
   t8.join();
}
1
Gupta

関数オブジェクトの追加メンバー関数ポインターは、呼び出し可能オブジェクトと呼ばれるものを生成します。 c ++ 98/03では、関数としてoperator()をオーバーライドするクラスを使用します。通常、そのクラス関数を呼び出します。関数の状態を保存できるという利点がありますが、他の関数では保存できないという利点があります。最も重要な概念。そして境界線では、このスタイルクラス関数と他のcスタイル関数およびcスタイル関数へのポインタを「関数オブジェクト」と呼びます。呼び出し可能オブジェクトは、単に「呼び出し可能」オブジェクトです。これには、関数オブジェクトとメンバー関数ポインターが含まれます。

1
Tu Xiaomi