Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clang: initialising a lock reference from a mutex

Tags:

c++

g++

clang

This program is compiled by clang:

#include <mutex>

int main() {
    std::mutex mtx;
    const std::lock_guard<std::mutex>& lock(mtx);
    return 0;
}

Other major compilers refuse it (I have tried gcc, msvc, and icc). This is an error message from gcc:

error: invalid initialization of reference of type ‘const 
       std::lock_guard<std::mutex>&’ from expression of type ‘std::mutex’

Others give similar errors.

Is clang right or wrong? Can this be reproduced with a simpler example not involving library classes? I have tried but to no avail.

Edit this seems to be the minimal reproduction:

struct A {};

struct X
{
    explicit X(A&) {};
};

int main()
{
    A a;
    const X& x(a);
}

Interestingly, an int in place of A does trigger the error message in clang (which is why I could not reproduce this initially).

like image 871
n. 1.8e9-where's-my-share m. Avatar asked Nov 13 '17 12:11

n. 1.8e9-where's-my-share m.


1 Answers

I don't have the relevant chapter and verse of the C++ standard; I can only refer to CppReference on Converting Constructors right now (emphasis mine):

A constructor that is not declared with the specifier explicit and which can be called with a single parameter (until C++11) is called a converting constructor.

Unlike explicit constructors, which are only considered during direct initialization (which includes explicit conversions such as static_cast), converting constructors are also considered during copy initialization, as part of user-defined conversion sequence.

So:

struct A {};

struct X
{
    explicit X(A const &) {};
};

int main()
{
    A a;
    const X& x1(A());                 // OK, direct init (no A object after init)
    const X& x3(a);                   // NOK, copy init
}
like image 198
DevSolar Avatar answered Oct 20 '22 18:10

DevSolar