2016-03-25 12 views
6

Załóżmy, że masz następujące klasy:Dlaczego nie można utworzyć pary z konstruktorem kopii "non const", skoro można go utworzyć bez niego?

struct A { 
    A() {} 
    A (A &) = delete; 
}; 

int main() { 
    std::pair<A, int> p1; 
    return 0; 
} 

Poniższy kod nie powiedzie się skompilować (używając -std=c++11 z g++) z powodu następującego błędu:

/usr/include/c++/5/bits/stl_pair.h: In instantiation of ‘struct std::pair’:

test.cpp:13:23: required from here

/usr/include/c++/5/bits/stl_pair.h:127:17: error: ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = A; _T2 = int]’ declared to take const reference, but implicit declaration would take non-const

constexpr pair(const pair&) = default; 

Zgodnie z komunikatem o błędzie, Przypuszczam dzieje się tak dlatego, że nie można zainicjować domyślnego konstruktora kopiowania ze względu na kwalifikator const dla argumentu std::pair.

Mogłem zrozumieć, dlaczego nie skompilowałoby się bez = delete, ponieważ nie można zainicjować konstruktora kopiowania, który ma parametr std::pair const&.

Ale z = delete, oczekiwałbym, że kompilator nie będzie tworzył takiego konstruktora, ponieważ nie może (o ile rozumiem). Właściwie, to konstruktor kopia zostanie usunięta, jak pokazano przez ten kawałek kodu:

std::pair<A, int> p1; 
decltype(p1) p2(p1); 

która nie:

test.cpp:11:23: error: use of deleted function ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = A; _T2 = int]’

decltype(p1) p2(p1); 

zasadzie moje pytanie brzmi: Dlaczego kompilator nie instancję usuniętą konstruktora kopii std::pair?

+0

Zobacz http://cplusplus.github.io/LWG/lwg-closed.html#2068 –

Odpowiedz

5

[class.copy]/8:

The implicitly-declared copy constructor for a class X will have the form

X::X(const X&) 

if each potentially constructed subobject of a class type M (or array thereof) has a copy constructor whose first parameter is of type const M& or const volatile M& . Otherwise, the implicitly-declared copy constructor will have the form

X::X(X&) 

Dlatego też, jeśli konstruktor kopia std::pair<A, int> miały być niejawnie zadeklarował, że będzie miał formę pair::pair(pair &).

[dcl.fct.def.default]/1:

A function that is explicitly defaulted shall

  • be a special member function,

  • have the same declared function type (except for possibly differing ref-qualifiers and except that in the case of a copy constructor or copy assignment operator, the parameter type may be “reference to non-const T ”, where T is the name of the member function's class) as if it had been implicitly declared, and

  • not have default arguments.

Ponieważ deklaracja pair(const pair&) = default; nie mają taką samą funkcję jak typ zadeklarowany konstruktor kopii, które zostałyby niejawnie zadeklarowanej, a nie wyjątek dotyczy, program jest źle sformułowane.

6

Jeśli chcesz = delete konstruktora kopiowania, prawidłowy formularz to: A(const A&) = delete;. Zobacz, jak zapomniałeś tego const? pair może być używany z typem, który nie może być kopiowany, nawet typu bez możliwości przenoszenia.

Twój problem instancji można także wykazać się:

struct A { 
    A(A&) = delete; 
}; 

struct B : A { 
    B(const B&) = default; 
}; 

lub ...

struct B { 
    B(const B&) = default; 
    A a; 
}; 

Zasadniczo pair= default jego kopia konstruktor i definiuje ją jako biorąc const pair&, ale jeden twoich typów definiuje, aby pobrać niezwiązaną wartość &, więc domyślne generowanie nie powiedzie się, ponieważ nie może przekazać swojej stałej & do twojej stałej &. Nawet jeśli Twój jest = delete ed, to nie ma znaczenia, nie zajdzie tak daleko.

Unieważniony egzemplarz ctor zostanie skutecznie usunięty, jeśli członek lub klasa bazowa nie będzie można skopiować. Ale żeby to zrozumieć, musi mieć funkcję, którą może wywołać (nawet jeśli ta funkcja jest usunięta). W takich przypadkach nie może przekazać stałej & do niestanowiącej &, więc nie może nawet dowiedzieć się, że masz usuniętego ctor. Niewykluczone, że coś w standardzie można zapisać, aby uwzględnić tę skrajną sprawę.

Powiązane problemy