2 votes

Choix de temps d'exécution du modèle C++

Je voudrais améliorer le code de sélection de modèle d'exécution suivant :

Nous avons 4 foncteurs pour le calcul de la norme p (1 cas général, 3 cas spécialisés). Pendant l'exécution, nous pouvons sélectionner le meilleur.

template 
struct p_norm { // contient des foncteurs pour calculer la norme p
    struct general { ... }; // cas général
    struct one { ... };     // spécialisation pour p=1
    struct two { ... };     // spécialisation pour p=2
    struct inf { ... };     // spécialisation pour p=inf
};

Par exemple, nous pouvons obtenir la distance en fonction de p,

auto impl_fptr = distance_fn::general>;
if (p == 1.0) {
  impl_fptr = distance_fn::one>;
} else if (p == 2.0) {
   impl_fptr = distance_fn::two>;
} else if (std::isinf(p)) {
   impl_fptr = distance_fn::inf>;
}
impl_fptr(vec1, vec2);

ou peut-être obtenir l'angle en fonction de p,

auto impl_fptr = angle_fn::general>;
if (p == 1.0) {
  impl_fptr = angle_fn::one>;
} else if (p == 2.0) {
   impl_fptr = angle_fn::two>;
} else if (std::isinf(p)) {
   impl_fptr = angle_fn::inf>;
}
impl_fptr(vec1, vec2);

Le problème est qu'il y a beaucoup de duplications de code dans la sélection d'un cas de modèle approprié. Je n'ai aucune idée sur la façon d'améliorer la sélection de type.

D'autre part, le problème mineur est que je voudrais mettre en œuvre p_norm pour le cas général et mettre en œuvre p_norm<1.>, p_norm<2.>, ... pour la spécialisation de modèle. Je sais que ce n'est pas ainsi que fonctionne le modèle, mais y a-t-il un moyen de rendre la spécialisation plus évidente ? Probablement via la répartition des balises ?

2voto

Jarod42 Points 15729

std::variant avec tag (std::type_identity ici) pourrait aider :

template 
std::variant::general>,
             std::type_identity::one>,
             std::type_identity::two>,
             std::type_identity::inf>>
get_method_var(double d)
{
    if (d == 1.0) { return std::type_identity::one>{}; }
    else if (d == 2.0) { return std::type_identity::two>{}; }
    else if (std::isinf(d)) { return std::type_identity::inf>{}; }
    else { return std::type_identity::general>{}; }
}

et puis

template 
auto distance(const auto& vec1, const auto& vec2, double p)
{
    return std::visit([&](auto tag){
            return distance_fn(vec1, vec2);
        }, get_method_var(p));
}

template 
auto angle(const auto& vec1, const auto& vec2, double p)
{
    return std::visit([&](auto tag){
            return angle_fn(vec1, vec2);
        }, get_method_var(p));
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X