ФИНАЛЬНОЕ ОБНОВЛЕНИЕ
После очень проницательного комментария @SebastianRedl я понял, что целью стандарта является обращение ко всей конструкции объекта, а не только к операциям внутри конструктора. Это означало бы, что в Visual C++ действительно есть ошибка. Тем не менее, я по-прежнему считаю, что формулировка стандарта недостаточно ясна, поэтому я оставлю остальную часть своего ответа без изменений для потомков.
Чтобы уточнить: поведение, упомянутое в OP, на самом деле является ошибкой, и в свете этого большая часть того, что я говорю ниже этого обновления, неверно.
Завершить обновление
На самом деле это не ошибка компилятора, а скорее странная особенность стандарта, поэтому ваше замешательство понятно.
Согласно стандарту C++11, следующее условие для того, чтобы is_trivially_constructible::value
было true
.
§20.9
is_constructible<T,Args...>::value
истинно, и известно, что определение переменной для is_constructible
, как определено ниже, не вызывает никакую операцию, которая не была бы тривиальной.
Таким образом, is_trivially_constructible
верно, пока данный тип можно построить с заданными аргументами и он не вызывает никаких нетривиальных операций. В вашем примере есть только один такой конструктор — конструктор копирования. На самом деле, по определению «нетривиальной операции» (по сути, нетривиального оператора или конструктора) это справедливо для вашего типа. Так что возвращение true
правильно.
Однако есть один очень странный момент! Стандарт C+11 говорит о конструкторах копирования следующее:
§12.8.12 (выделено мной)
Конструктор копирования/перемещения для класса X тривиален, если он не предоставляется пользователем и если
- класс X не имеет виртуальных функций (10.3) и виртуальных базовых классов (10.1), и
- конструктор, выбранный для копирования/перемещения каждого прямого подобъекта базового класса, тривиален, и
для каждого нестатического члена данных X, который имеет тип класса (или его массив), конструктор, выбранный для копирования/перемещения этого члена, является тривиальным;
в противном случае конструктор копирования/перемещения нетривиален.
Поскольку вы предоставляете пользовательский конструктор копирования, ваш класс не является тривиально копируемым. Указанный вами конструктор копирования не тривиален. Тем не менее, нетривиальный конструктор копирования выполняет необходимые условия для того, чтобы is_trivially_constructible
возвращал true
с аргументом, который соответствует вашему конструктору копирования.
На мой взгляд, это больше похоже на «ошибку» в стандарте. is_trivially_constructible
возвращает, является ли тип тривиально конструируемым с учетом определенных аргументов. Похоже, это не гарантирует, что сам конструктор считается тривиальным!
Обновление:
После попытки разработать тест, демонстрирующий следующий случай, я обнаружил ошибку в VC11. Логика, описанная стандартом, означает, что если B
используется в качестве подобъекта (члена или базы) другого типа, любой конструктор этого типа, который вызывает конструктор копирования B
, должен считаться нетривиальным сильный> от std::is_trivially_constructible
. В VC11 такого нет.
Пример кода
#include <iostream>
#include <type_traits>
struct B
{
B() {}
B(B&) {
std::cout << "not trivial\n";
}
};
struct A : B
{
A(B& B) : b(B){}
B b;
};
int main()
{
std::cout << std::is_trivially_constructible<B, B&>::value << '\n'; // Should print 1
std::cout << std::is_trivially_constructible<A, B&>::value << '\n'; // Should print 0
getchar();
return 0;
}
person
Agentlien
schedule
26.04.2013