2014-09-04 2 views
7

Посмотрите на код:Почему я могу использовать собственный конструктор по умолчанию в 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 является частным.

However, it works well. Я испытал это на своем g ++ 4.8.3 с -Wall -Wextra -Werror -pedantic в недоумении, но он хорошо работает без каких-либо ошибок или предупреждений.

(Кроме того, кажется, работает хорошо в GCC 4.9.1, а также.)

Из this page, я думаю, мы можем использовать приватный конструктор по умолчанию, если выражение невычисленное. Итак, я проверил следующее, чтобы проверить это.

#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 
} 

(live example)

Как и ожидалось, он не был составлен.

Но .... Почему? Как это возможно? Можем ли мы использовать частных пользователей в неудовлетворительном выражении? Или существует специальное правило для конструкторов по умолчанию? Не могли бы вы объяснить мне, почему?

+0

Не компилируется в clang. –

+0

@ T.C. Да неужели? то это может быть просто ошибка GCC .. – ikh

+1

Ум, C++ 98 не имеет 'decltype'. Или 'declval'. Конечно, он не компилируется. –

ответ

11

Не следует компилировать. C++ 11 [class.temporary] это сказать о создании временного объекта:

12,2/1 Даже когда создание временного объекта невычисленных или иначе избежать, всех семантических ограничений должны соблюдаться, как если бы временный объект был создан и впоследствии уничтожен. [Примечание:, даже если нет вызова деструктора или конструктора копирования/перемещения, все семантические ограничения , такие как доступность и функция удаляется, должны быть выполнены. Однако в специальном случае вызова функции, используемого в качестве операнда decltype-specifier, не вводится никаких временных ограничений, поэтому вышеизложенное не применяется к назначению любого такого вызова функции. - конец примечание]

Таким образом, даже когда невычисленного, вы все еще ограничены доступностью любых функций (включая конструкторы), которые необходимы для создания и уничтожить временный. В последнем предложении примечания разъясняется, что для предотвращения этого препятствия можно использовать такую ​​функцию, как declval.

+1

Спасибо , +1 для * окончательного предложения *. (о, я вижу, я не могу принять ответ за одну минуту> o <) – ikh

+0

Тогда это должна быть ошибка gcc; я должен сообщить об этом? > О < – ikh

Смежные вопросы