Недавно я попытался обнаружить существование определенных частных конструкторов и столкнулся с проблемой, что std::is_constructible
проверяет только непосредственный контекст и, следовательно, не распознает ничего таких конструкторов. После некоторого исследования я увидел, что в одном ответе здесь упоминается, что правильным способом является подружка рассматриваемого класса с std::is_constructible
, чтобы он имел доступ.
Чтобы проверить, работает ли этот метод, я попытался выполнить следующий тестовый код
#include <type_traits>
class A {
private:
template<typename, typename ...>
friend struct std::is_constructible;
A() = default;
};
int main() {
static_assert(std::is_constructible<A>::value);
static_assert(std::is_constructible_v<A>);
}
Интересно, что этот метод действительно работал с std::is_constructible
в Visual Studio 2017, хотя я тогда начал сталкиваться с проблемами с std::is_constructible_v
. В их реализации, вместо того, чтобы использовать шаблон псевдонима для самой структуры std::is_constructible
, они вместо этого напрямую вызывают внутреннее свойство, используемое внутренне, что в свою очередь игнорирует объявление друга.
Думая, что это было ошибкой в их стандартной реализации библиотеки, я затем протестировал в других компиляторах и обнаружил, что ни clang, ни gcc ни в коем случае не могли пропустить это утверждение, что заставило меня задуматься, может ли оно вообще работать как это вообще (некоторые комментарии в связанном посте, кажется, предполагают, что это ошибка, в то время как другие говорят, что это не должно принимать во внимание объявления друзей).
Таким образом, главный вопрос заключается в том, должен ли этот код работать правильно (как он должен иметь возможность доступа к приватному конструктору и передавать утверждения) так, как стандарт определяет доступ, ограниченный непосредственным контекстом? Подобный вопрос был также поставлен здесь , главное, в чем я не уверен, это точное определение, подразумеваемое «непосредственным контекстом» в этом случае, поскольку это немного отличается от примера в связанном вопросе.
Соответствующий отрывок из N4713 23.15.4.3.8 [meta.unary.prop] / 8:
Проверка доступа выполняется, как будто в контексте, не связанном с T и любым
Args. Только действительность непосредственного контекста
инициализация переменной считается.