2011-09-12 9 views
7

Obecnie jednym z moich szablonów klas zabawka ma dwa konstruktory, które wyglądają bardzo podobnie:połączenie dwóch konstruktorów że kopiować i przenosić

optional(const T& x) 
{ 
    construct(x); 
} 

optional(T&& x) 
{ 
    construct(std::move(x)); 
} 

można połączyć je w jeden szablon konstruktora, czy będzie się to zmienić semantykę jakoś ?

template<typename U> 
optional(U&& x) 
{ 
    construct(std::forward<U>(x)); 
} 
+0

jakie jest prawdziwe mięso "konstruktu"? –

+0

@Alf: brzydkie umieszczanie nowych rzeczy na wyrównanym schowku :) – fredoverflow

Odpowiedz

2

zmienia to sposób, cechy takie jak std::is_constructible i std::is_convertible interakcji z optional . Na podanym przykładzie:

class A {}; 

int main() 
{ 
    std::cout << std::is_constructible<optional<A>, int>::value << '\n'; 
}; 

Twój oryginalny kod będzie drukować:

0 

Ale Twój nowy kod wypisze:

1 

Jeśli jest niepożądany, a mimo to chcesz przejdź do nowego kodu, możeszgo ograniczyć U do akceptowalnych typów.

Jedyny inny możliwy problem, który widzę, to: T może być typem odniesienia (np. int&).W takim przypadku drugi konstruktor oryginalnego kodu wygląda podejrzanie, ponieważ przechodziłby on w wartość rwart, a ty możesz próbować związać tę wartość r do nieokreślonego odwołania do lwartości (nie można powiedzieć na pewno). Jeśli T nigdy nie może być typem odniesienia, nie musisz się tym martwić.

4

Konstruktor szablonów nigdy nie będzie (uważany przez kompilator za) konstruktorem kopii, przepraszam.

+0

Erm, 'opcjonalne (const T &)' nie jest nawet konstruktorem kopii, co myślałem? edytowane – fredoverflow

+0

@Fred: w takim przypadku, należy rozważyć zastosowanie przesyłania konstruktora C++ 11? jeśli jest zaimplementowany przez kompilator jeszcze. nie wiem, które kompilatory go obsługują, jeśli takie istnieją. alternatywnie, jeśli nie jest obsługiwany, możesz użyć sztucznej klasy bazowej. przekazuje wywołanie konstruktora do klasy bazowej. –

+0

Oh, 'construct' nie jest konstruktorem, jest to szablon funkcji członka. – fredoverflow

1

Och, konstrukcja nie jest konstruktorem, jest to szablon funkcji członka.

Wtedy prawdopodobnie semantyka jest inna. Twój oryginalny zestaw przeciążeniowy przekazuje albo wartość bezwzględną do stałej, albo wartość rwartości do wartości stałej. Wersja szablonu może również przekazać wartość l-wartości do non -const. (Jestem ignorując rvalue odniesień do const.)

Według wszelkiego prawdopodobieństwa wysokiej chociaż construct albo jest uznany zaakceptować U&& (jeszcze poprzedni przeciążenie, które przenosi T nie będzie działać) i w tym przypadku powinien czynienia z nie -const wartości lub jest uznany za akceptujący U const& iw tym przypadku jest nieszkodliwy.

0

Zakładając, że masz co najmniej construct(const T& x) i ewentualnie dodanie construct(T&& x) zdefiniowany, a twój obiekt typu U jest convertable do obiektu typu T, myślę, że powinno być w porządku ...

  1. Stała wartość odniesienia L typu U zwiąże się construct(const T& x)
  2. o niestałym odniesienia L wartość typu U zwiąże się construct(const T& x)
  3. tymczasowe wartość r typu U zostanie wiązać construct(T&& x) lub construct(const T& x) Jeśli wersja referencyjna wartość R nie jest zdefiniowany
  4. Stała odniesienia wartość R typu U zwiąże się construct(const T& x)
Powiązane problemy