Depuis l'apprentissage de la rouille, je suis devenu fan de la Newtype idiom que je suppose Rust emprunté de haskell .
Un nouveautype est un type distinct basé sur un type standard qui garantit que les paramètres de fonction sont du type correct.
[.____] Par exemple, le old_enough
La fonction ci-dessous doit être transmise d'un âge pendant des années. Il ne compilera pas avec un âge en jours ou comme un broiseau I64.
struct Days(i64);
struct Years(i64);
fn old_enough(age: &Years) -> bool {
age.0 >= 18
}
Ceci est différent d'un typedef
ou using
Déclaration en C++ qui renomme simplement le type.
[.____] Par exemple, le old_enough
la fonction ci-dessous accepterait un int
, un âge dans Days
ou quoi que ce soit d'autre qui convertit sur un int
:
typedef int Days;
using Years = int;
bool old_enough(Years age) {
return age >= 18;
}
Comme l'exemple ci-dessus utilise simplement des entiers, Ceci Post sur Reddit suggère d'utiliser des classes Enum, E.G.:
enum class Days : int {};
enum class Years : int {};
bool old_enough(Years age) {
return static_cast<int>(age) >= 18;
}
Ou cela pourrait simplement utiliser des structures, comme Rust E.g.:
struct Days final {int value;};
struct Years final {int value;};
bool old_enough(Years age) {
return age.value >= 18;
}
Quelle est la meilleure façon de mettre en œuvre le newtype
idiome dans C++
?
[.____] Y a-t-il une méthode standard?
[~ # ~ ~] Edit [~ # ~] La question fortement tapé à l'aide de TypeDef est similaire. Cependant, il ne considère pas le newtype
idiome.
Si vous avez - boost , boost_strong_typedf fait exactement ce que vous voulez comme déjà vu dans cette réponse .
Il n'y a rien dans la langue C++ (encore) qui peut le faire directement comme vous le souhaitez. Mais encore une fois, des besoins détaillés pourraient être différents, par exemple. Quelqu'un pourrait dire que c'est bien de faire une construction implicite où une autre pourrait dire que cela doit être explicite. En raison de combinaisons et autres 1 Il est difficile de fournir un mécanisme qui satisfera tout le monde et que nous avons déjà un alias de type normal (c.-à-d. using
, lequel de l'OFC. est différent d'un fort Typedef ).
Cela étant dit, C++ vous donne vous-même suffisamment d'outils que vous pouvez construire cet outil générique et il n'est pas complètement difficile de faire si vous avez une expérience avec modèles , etc.
À la fin, cela dépend de quoi NEWTYPE Les problèmes que vous avez réellement, par exemple. Avez-vous juste besoin d'une poignée ou allez-vous les faire en blocs? Pour quelque chose d'ordinaire comme des années et des jours, vous pouvez simplement utiliser des structures nues:
struct Days {int value;};
struct Years {int value;};
Cependant, si vous devez éviter une situation comme celle-ci:
bool isold(Years y);
...
isold({5});
Vous devez ensuite faire un constructeur et le rendre explicite, à savoir:
struct Years {
explicit Years(int i);
...
1 Une autre combinaison pourrait par exemple être si le nouveau type doit être autorisé à convertir au type sous-jacent, pourrait être utile pour quelque chose comme int
, ou cela pourrait être dangereux en fonction du contexte