Prenons la déclaration de fonction suivante:
void print(SomeType const* i);
Ici le const*
nature de l'argument i
suggère l'intention, que le paramètre est en option, car il peut être nullptr
. Si cela n'était pas prévu, l'argument serait plutôt un const&
. Communication Facultatif - La sémantique n'était certainement pas l'intention d'origine pour la conception des pointeurs, mais les utiliser pour le faire, il arrive de fonctionner très bien pendant une longue période.
Maintenant, étant donné que l'utilisation des pointeurs bruts est généralement découragé dans le C++ moderne (et doit être évité en faveur de std::unique_ptr
et std::shared_ptr
Pour indiquer précisément particulier Propriété - Sémantique), je me demande comment indiquer correctement les paramètres de fonction ' Facultatif - Sémantique Sans passer de la valeur , i. e. Copie , comme
void print(std::optional<SomeType> i);
ferait.
Après avoir pensé pendant un moment où j'ai eu l'idée d'utiliser:
void print(std::optional<SomeType const&> i);
Cela serait en fait plus précis. Mais il s'avère que std::optional
ne peut pas avoir de types de référence . ¹
Aussi, en utilisant
void print(std::optional<SomeType> const& i);
ne serait en aucun cas optimale, puisque nous le ferions besoin Notre SomeType
_ pour exister dans un std::optional
sur le appelant - Côté, encore éventuellement (ou plutôt probablement) nécessitant une copie là-bas.
Question: Quelle serait une bonne approche moderne pour permettre des arguments facultatifs sans copier? Utilise un pointeur brut ici encore une approche raisonnable en C++ moderne?
¹: ironiquement la raison décrite pour la raison pour laquelle std::optional
ne peut pas avoir de types de référence (la controverse sur la reproduction ou la transmission à l'affectation) ne s'applique pas dans le cas de std::optional
s of const Références, car elles ne peuvent pas être affectées à.
Ici le
const*
nature de l'argumenti
suggère l'intention, que le paramètre est facultatif car il peut être nullptr.[...]
Alors quelle serait une bonne approche moderne pour permettre des arguments facultatifs sans copier?
Permettant un argument facultatif (pas dans le std::optional
Sens, mais dans le sens sémantique), avec différentes variations de mise en œuvre, selon que l'argument facultatif soit présent ou non comme un candidat idéal pour la surcharge:
struct SomeType { int value; };
namespace detail {
void my_print_impl(const SomeType& i) {
std::cout << i.value;
}
} // namespace detail
void my_print() {
const SomeType default_i{42};
detail::my_print_impl(default_i);
}
void my_print(const SomeType& i) {
detail::my_print_impl(i);
}
ou alors
namespace detail {
void my_print_impl() {
std::cout << "always print me\n";
}
} // namespace detail
void my_print() {
detail::my_print_impl();
}
void my_print(const SomeType& i) {
detail::my_print_impl();
std::cout << "have some type: " << i.value;
}
ou une variation similaire, en fonction de la mise en œuvre de votre mise en œuvre en fonction de l'existence/de la non-existence de l'argument facultatif.
Les références facultatives, sinon, sont essentiellement des pointeurs bruts et ce dernier peut aussi bien être utilisé (si la surcharge n'est pas applicable).
C'est en fait ce que STD :: référence_wrapper a été fait pour. Voir aussi a du logique de combiner optionnelle avec référence_wrapper? Pour plus de raisonnement sur le point de l'utiliser, et quand ne pas l'utiliser.