В Visual C ++ 2010 у меня есть такой класс:
class MyClass{
public:
MyClass(){}
MyClass(MyClass &){/*...*/} //A
MyClass(const MyClass &){/*...*/} //B
template<typename T> MyClass(T &&t){ static_assert(
!std::is_same<typename
std::remove_cv<typename std::remove_reference<T>::type>::type,
MyClass>::value,
"Wrapping over wrapping is not allowed!"); } //C
};
int main(int, char**){
MyClass a;
const MyClass b(a); //assert fail if line A removed
auto c=b; //assert fail if line B removed
}
//If both A and B exists
//Warning C4521: multiple copy constructors specified
//Furthermore, if both A and B removed
//No error or warnings; VC2010 accepts peacefully.
//In debug mode you will find the compiler generated trivial copy constructor
В соответствии со стандартом C ++ обе строки A и B считаются конструкторами копирования, а C - конструктором преобразования. Не удивительно, что я получаю предупреждение о том, что я объявил несколько конструкторов копирования. Однако, если я удалю какой-либо из них, static_assert завершится неудачно и код не будет скомпилирован, это означает, что конструктор шаблона получил управление.
Я уверен, что это поведение следует правилу перегрузки функций. Однако это конфликт двух правил? Если A и B являются конструкторами копирования, и один из них был объявлен, любая попытка копирования объектов не должна сбрасываться в шаблон, верно?
Обновление:
Согласно N3242, 12.8.7,
"шаблон функции-члена НИКОГДА НЕ УСТАНАВЛИВАЕТСЯ выполнять копирование объекта класса в объект его типа."
правильная реализация должна быть:
- Не должно произойти сбоя подтверждения при удалении либо A, либо B, либо обоих.
- Если строка B удалена, конструкция c должна потерпеть неудачу, потому что b является const.
- Если обе строки удалены, компилятор должен сгенерировать конструктор копирования для класса.
- Реализация должна предупредить пользователя, если обе строки существуют.
Любой комментарий?