std :: is_constructible повертає непослідовне значення для приватного конструктора


13

Які правила 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насправді це непослідовно?


1
Виглядає як помилка GCC, відбитки00
clang

1
Ще одна дивна думка, яку я помічаю при компілюванні на моїй машині з c ++ 17 g ++ 9.2.1 / g ++ - 10.0 і заміні std :: is_constructible <...> :: значення на is_constructible_v <...>, це те, що результат змінюється на 00
mutableVoid

1
@mutableVoid Дійсно - і здається, що ::valueверсія здатна змінити вихід тих, хто надходить і до неї: godbolt.org/z/zCy5xU Відкоментуйте коментований рядок і все стає 1: s у gcc.
Тед Лінгмо

1
Ще один спосіб виправити це: godbolt.org/z/EKaP3r, тому в основному це якась помилка порядку замовлення.
Marek R

2
@mutableVoid Вам навіть не потрібно створювати шаблон функції, щоб він став істинним. У цьому прикладі він повертається, falseале якщо шаблон функції не коментується, він раптово повертається true: godbolt.org/z/zqxdk2
Тед Лінгмо

Відповіді:


3

std::is_constructibleповинен повернутися falseв цьому сценарії, оскільки конструктор недоступний.

Як зазначено під питанням, поведінка, описана в питанні, викликана помилкою в GCC / libstdc ++. Тут повідомляється про помилку , і, за словами Bugzilla, пов’язана з помилкою, якщо вона не була викликана помилкою контролю доступу для класів у шаблонових функціях, яка вже давно не була вирішена. Взаємозв’язок між двома помилками взято з коментаря Bugzilla Джонатана Уейклі, який, здається, спочатку виявив зв’язок між двома помилками.

Це також має на увазі той факт, що поведінка цього сценарію в GCC стає правильною при видаленні конструктора замість того, щоб зробити його приватним:

class Class {
    Class() = delete;
};

який друкує 0і 00відповідно. Це правильний вихід (який clangправильно повідомляє у сценарії з приватним конструктором також).

Це може пояснити спостережувану зміну поведінки під час коментування в рядку, оскільки всередині функції в шаблонній структурі перевірка доступу не працює і повідомляє, що конструктор доступний, коли його немає. Коли ознака перевіряється ще раз у наступному рядку або, можливо, у зовсім іншому місці (як це відбувається у нас ), вона вже була створена, і, таким чином, дає неправильну відповідь.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.