jeudi 4 mai 2017

By-ref arguments: is this an inconsistency between std::thread and std::bind?

std::bind and std::thread share a few design principles. Since both of them store local objets corresponding to the passed arguments, we need to use either std::ref or std::cref if reference semantics is desired:

void f(int& i, double d) { /*...*/ }

void g() {
    int x = 10;
    std::bind(f, std::ref(x), _1) (3.14);
    std::thread t1(f, std::ref(x), 3.14);
    //...
}

But I'm intrigued by a recent personal discovery: std::bind will allow you to pass a value in the case above, even though this is not what one usually wants.

    std::bind(f, x, _1) (3.14); // Usually wrong, but valid.

However, this is not true for std::thread. The following will trigger a compile error.

    std::thread t2(f, x, 3.14); // Usually wrong and invalid: Error!

At first sight I thought this was a compiler bug, but the error is indeed legitimate. It seems that the templated version of std::thread's constructor is not able to correctly deduce the arguments due to the copy decaying requirement (tranforming int& in int) imposed by 30.3.1.2.

The question is: Why not require something similar to std::bind's arguments? Or is this apparent inconsistency intended?

Aucun commentaire:

Enregistrer un commentaire