Почему я могу использовать закрытый конструктор по умолчанию в decltype()?
Посмотрите на код:
#include <iostream>
#include <utility>
class test
{
private:
test() { }
public:
test foo() { return *this; }
static const char *name() { return "test"; }
};
int main()
{
std::cout << decltype(test().foo())::name() << std::endl; // 1
std::cout << decltype(std::declval<test>().foo())::name() << std::endl; // 2
}
Я ожидал, что строка // 1
не может быть скомпилирована, потому что конструктор по умолчанию test
является частным.
Тем не менее, это работает хорошо. я протестировал его на моем g++ 4.8.3 с -Wall -Wextra -Werror -pedantic
в неверии, но он работает хорошо без каких-либо ошибок или предупреждений.
(кроме того, он, по-видимому, хорошо работает и в GCC 4.9.1.)
Из этой страницы , я думаю, мы можем использовать частный конструктор по умолчанию, если выражение не оценено. Итак, я проверил следуя, чтобы проверить это.
#include <iostream>
#include <utility>
class test
{
private:
test(int) { }
public:
test foo() { return *this; }
static const char *name() { return "test"; }
};
int main()
{
std::cout << decltype(test().foo())::name() << std::endl; // 1
std::cout << decltype(std::declval<test>().foo())::name() << std::endl; // 2
}
Как и ожидалось, он не был скомпилирован.
Но.... почему?? Как это может быть возможно? Можем ли мы использовать частные члены в ненулевом выражении? Или существует специальное правило для конструкторов по умолчанию? Не могли бы вы объяснить мне, почему?
1 ответ:
Он не должен компилироваться. C++11 [класс.temporary] имеет это сказать о создании временного объекта:
Таким образом, даже когда вы не оцениваете, вы все еще ограничены доступностью любых функций (включая конструкторы), необходимых для создания и уничтожения временного. Финал предложение Примечания уточняет, что функция, подобная12.2 / 1 Даже если создание временного объекта не оценено все семантические ограничения должны соблюдаться, как если бы временный объект был создан, а затем уничтожен. [Примечание: даже если нет вызова деструктора или конструктора копирования / перемещения, все семантические ограничения , такие как доступность и будет ли функция удалена, должно быть удовлетворено. Однако в частном случае вызова функции, используемой в качестве операндаописателя decltype , не вводится временное значение, поэтому вышеизложенное не относится к prvalue любого такого вызова функции. - Конечная нота]
declval
, может быть использована, чтобы избежать этого препятствия.