Каковы правила, по которым std::is_constructible
обрабатываются частные конструкторы? Учитывая следующий код:
#include <iostream>
class Class {
private:
Class() { }
};
template <typename T>
class Test {
public:
static void test() {
std::cout
//<< std::is_constructible<Class>::value
<< std::is_constructible<T>::value
<< std::endl;
}
};
int main() {
Test<Class>::test();
}
Это печатает 0
( ideone ), т. Е.T
Не является конструируемым по умолчанию.
Раскомментируя закомментированную строку, она печатает 11
( ideone ), поэтому T
неожиданно стала конструируемой по умолчанию.
Я мог бы найти обоснование для поддержки обоих результатов, но я не понимаю, как включение закомментированной строки меняет результат второго. Это как-то вызывает UB? Это ошибка компилятора? Или это std::is_constructible
действительно противоречиво?
c++
typetraits
zennehoy
источник
источник
00
::value
версия способна изменить вывод тех, кто ей предшествует: godbolt.org/z/zCy5xU Раскомментируйте закомментированную строку, и все станет 1: s в gcc.false
но если шаблон функции не закомментирован, он неожиданно возвращаетtrue
: godbolt.org/z/zqxdk2Ответы:
std::is_constructible
должен вернутьсяfalse
в этом сценарии, потому что конструктор не доступен.Как указано под вопросом, поведение, описанное в вопросе, вызвано ошибкой в GCC / libstdc ++. Об этой ошибке сообщается здесь , и, согласно Bugzilla, она связана с, если не вызвана, ошибкой контроля доступа для классов в шаблонных функциях , которая не устранена в течение достаточно долгого времени. Взаимосвязь между двумя ошибками взята из комментария Джонатана Уэйкли к Bugzilla, который, похоже, первым обнаружил связь между двумя ошибками.
Это также подразумевается тем фактом, что поведение этого сценария в GCC становится правильным при удалении конструктора вместо того, чтобы сделать его закрытым:
который распечатывает
0
и00
соответственно. Это правильный вывод (которыйclang
правильно сообщает в сценарии с частным конструктором, а также).Это может объяснить наблюдаемое изменение поведения при комментировании в строке, потому что внутри функции в шаблонной структуре проверка доступа не работает и сообщает, что конструктор доступен, когда это не так. Когда черта проверяется снова в следующей строке или , возможно , в совершенно другом месте (как это имеет место здесь ), он уже был создан экземпляр, и , таким образом , дает неправильный ответ.
источник