3

After I posting this question I tried to reproduce the problem of accidental rvalue creation when creating a scoped RAII object. Now it appears that I can't reproduce it without compiler errors!

In the following code sample, in Test::foo() the second ScopedLock creation doesn't compile. The gcc compiler error seems totally wrong. Can anyone explain?

struct Mutex
{
    void lock() { }

    void unlock() { }
};


struct ScopedLock
{
    ScopedLock(Mutex & inMutex) : mMutex(inMutex)
    { mMutex.lock(); }

    ~ScopedLock()
    { mMutex.unlock(); }

private:
    ScopedLock(const ScopedLock&);
    ScopedLock& operator=(const ScopedLock&);

    Mutex mMutex;
};


struct Test
{
    void foo()
    {
        // Compiles fine
        ScopedLock lock(mMutex);

        // Error: no matching function for
        // call to ‘ScopedLock::ScopedLock()’
        ScopedLock(mMutex);
    }

    Mutex mMutex;
};

I'm using GCC 4.2.1 on Mac.

Update

I had a look at the original code and saw that the member was referenced through the this pointer:

ScopedLock(this->mMutex); // short-lived temporary and compiles fine
Community
  • 1
  • 1
StackedCrooked
  • 34,653
  • 44
  • 154
  • 278
  • 3
    Heh, I wondered about this on your previous question... The syntax implies a function call, not a temporary object. You may wish to ask your co-worker if his situation wasn't a *bit* more involved than he made it out to be. – Shog9 Mar 01 '11 at 19:47
  • Yes, I'm definitely going to check it out tomorrow. – StackedCrooked Mar 01 '11 at 20:07
  • @Shog9 It turns out he used the following syntax: `ScopedLock(this->mutex);`. Which compiles fine. – StackedCrooked Mar 02 '11 at 19:10

2 Answers2

5

You have two user declared constructors, so there is no compiler generated default one.

Yes,

Type (i);

is handled in the same way as

Type i;

Such parenthesis are useful in more complex declarations such as

Type (*i)();

to declare a pointer to a function returning a type.

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
0

The message is telling you that ScopedLock doesn't have a default constructor, i.e. one that takes no arguments. If you declare a constructor that takes arguments, C++ won't create a default one for you.

ceo
  • 1,138
  • 1
  • 8
  • 16
  • GCC is correct that there is indeed no default constructor. However, the constructor that I'm calling is not the default one. It's the one that takes a `Mutex&` argument. – StackedCrooked Mar 01 '11 at 19:57
  • 1
    No, according to gcc you're creating a ScopedLock called mMutex. Add the () ctor, then call mMutex.lock() after the ScopedLock(mMutex) call, it'll complain that ScopedLock doesn't have a lock member function – Erik Mar 01 '11 at 19:59
  • @Erik, it seems you're right. Is GCC in the wrong here or is my code illegal? – StackedCrooked Mar 01 '11 at 20:08
  • Without reading through the standard, I think GCC is right. MSVC gives a corresponding error message. – Erik Mar 01 '11 at 20:10