Czy wszystkie / większość funkcji ustawiających w C ++ 11 powinny być zapisane jako szablony funkcji akceptujące uniwersalne odwołania?
Rozważ klasęX
zN
zmienne członkowskie, każda z nichcopiable iruchomy typ iN
odpowiednie funkcje setera. W C ++ 98 definicjaX
prawdopodobnie wyglądałby mniej więcej tak:
class X
{
public:
void set_a(A const& a) { _a = a; }
void set_b(B const& b) { _b = b; }
...
private:
A _a;
B _b;
...
};
Funkcje seterów klasyX
powyżej może wiązać zarówno wartość l, jak i wartość argumentów. W zależności od faktycznego argumentu, tomoc spowodować utworzenie tymczasowego ibędzie ostatecznie doprowadzić do przypisania kopii; z tego powodunie do skopiowania typy nie są obsługiwane przez ten projekt.
W C ++ 11 mamy semantykę przenoszenia, doskonałe przekazywanie i uniwersalne odniesienia (terminologia Scotta Meyersa), które pozwalają na bardziej wydajne i uogólnione korzystanie z funkcji ustawiających, przepisując je w ten sposób:
class X
{
public:
template<typename T>
void set_a(T&& a) { _a = std::forward<T>(a); }
template<typename T>
void set_b(T&& b) { _b = std::forward<T>(b); }
...
private:
A _a;
B _b;
...
};
Powszechne odniesienia mogą się wiązać zconst
/nie-const
, volatile
/nie-volatile
, oraz do dowolnego typu przekształcalnego w ogóle, unikając tworzenia tymczasowych i przekazując wartości prosto dooperator =
. Nie do skopiowania, ruchomy typy są teraz obsługiwane. Prawdopodobnie niepożądane wiązania można wyeliminowaćstatic_assert
lub przezstd::enable_if
.
Moje pytanie brzmi: jakwytyczne projektowe, czy wszystkie (powiedzmy, większość) funkcji ustawiających w C ++ 11 powinny być zapisane jako szablony funkcji akceptujące uniwersalne odwołania?
Oprócz bardziej kłopotliwej składni i niemożności użycia narzędzi pomocniczych podobnych do Intellisense podczas pisania kodu w tych funkcjach ustawiających, czy istnieją jakieś istotne wady hipotetycznej zasady „funkcje ustawiania zapisu jako szablony funkcji akceptujące uniwersalne odwołania, gdy tylko jest to możliwe„?