Инициализация скобок предотвращает неконстантное использование временных
Я хочу создать временную копию объекта const и использовать его неконстантным способом:
struct S {
S& f() { return *this; }
};
int main() {
const S a{};
S{a}.f(); // Error on this line
return 0;
}
Используя msvc (Visual Studio 2017, С++ 14), я получаю эту ошибку:
Ошибка C2662 & S:: f (void) ': не может преобразовать указатель 'this' из' const S 'в &'
Если я изменил инициализацию скобки на классическую инициализацию, она работает:
S{a}.f(); // Does not work
S(a).f(); // Works
Оба варианта компилируются в gcc. Я что-то упустил или это ошибка компилятора?
Ответы
Ответ 1
Похоже на ошибку компилятора или на результат странной оптимизации, поскольку этот вариант исходного кода, который делает только ctors и dtor с побочными эффектами, компилируется с использованием 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;
}
Компиляция выполнена успешно, а вывод:
Default ctor 0306FF07
Copy ctor 0306FF07 -> 0306FF06
Dtor 0306FF06
Dtor 0306FF07
Ответ 2
Похоже на другую ошибку MSVC.
S{a}
выводится как const struct S
, и это само по себе является ошибкой.
#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;
}
Вывод:
const struct S