Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Brace initialization prevents non-const use of temporary

I want to create a temporary copy of a const object and use it in a non-const way:

struct S {
    S& f() { return *this; }
};

int main() {
    const S a{};
    S{a}.f(); // Error on this line
    return 0;
}

Using msvc (Visual Studio 2017, C++14), I get this error:

Error C2662 'S &S::f(void)': cannot convert 'this' pointer from 'const S' to 'S &'

If I change the brace initialization to classic initialization, it works:

S{a}.f(); // Does not work
S(a).f(); // Works

Both variants compile fine in gcc. Am I missing something or is this a compiler bug?

like image 663
Beta Carotin Avatar asked Mar 31 '17 11:03

Beta Carotin


2 Answers

Seems like another MSVC bug.

S{a} is deduced as const struct S, and that alone is bug.

#include <string>
#include <iostream>

template < class T >
std::string type_name()
{
    std::string p = __FUNCSIG__;
    return p.substr( 106, p.length() - 106 - 7 );
}


struct S {
    S& f() { return *this; }
};

int main() {
    const S a{};
    //S{a}.f(); // Error on this line
    std::cout << type_name<decltype(S{a})>() << std::endl;
    return 0;
}

Output:

const struct S
like image 112
xinaiz Avatar answered Oct 03 '22 11:10

xinaiz


It looks like a compiler bug, or the result of a weird optimization, because this variation of original code that only make ctors and dtor with side effects compiles fine using MSVC:

#include <iostream>

struct S {
    S(const S& other) {
        std::cout << "Copy ctor " << &other << " -> " << this << std::endl;
    }
    S() {
        std::cout << "Default ctor " << this << std::endl;
    }
    ~S() {
        std::cout << "Dtor " << this << std::endl;
    }
    S& f() { return *this; }
};

int main() {
    const S a{};
    std::cout << &a << std::endl;
    S{a}.f();
    return 0;
}

Compilation is successful and output is:

Default ctor 0306FF07
Copy ctor 0306FF07 -> 0306FF06
Dtor 0306FF06
Dtor 0306FF07
like image 22
Serge Ballesta Avatar answered Oct 03 '22 09:10

Serge Ballesta