J'ai une situation où mon opérateur de module de modèle joue bien entre les flottants et les types entiers. Si je me souviens bien, il existe un moyen de lui faire sélectionner le plus spécifique sur le champ d'application plus large, mais je n'arrive pas à trouver ou à me rappeler comment faire cela.

Fondamentalement, j'ai 2 méthodes qui sont colidantes (erreur de redéfinition.)

Ce que j'essaie de faire, c'est d'obtenir la surcharge d'opérateur de module spécialisé à utiliser lorsque son type (T_COORDS) est float, le plus large quand il n'est pas float.

Le spécialisé (notez qu'il utilise la fonction math fmod):

template <size_t N
    , enable_if_t<N != 0 && N <= C_COORDS*N_COORDS && N % C_COORDS == 0, bool> = false>
friend Coords operator % (const Coords<float,C_COORDS,N_COORDS>& coords0, const auto (& coords1)[N])
{
  Coords<float,C_COORDS,N_COORDS> result = coords0;
  for (int i=0; i < C_COORDS*N_COORDS; i++)
      result.coords[i] = fmod(result.coords[i], coords1[i%N]);
  return result;
}

Le plus large (notez qu'il utilise le module flottant standard):

template <std::size_t N
    , std::enable_if_t<N != 0 && N <= C_COORDS*N_COORDS && N % C_COORDS == 0
    , bool> = false>
friend Coords operator % (const Coords<T_COORDS,C_COORDS,N_COORDS>& coords0, const auto (& coords1)[N])
{
  Coords<T_COORDS,C_COORDS,N_COORDS> result = coords0;
  for (int i=0; i < C_COORDS*N_COORDS; i++)
      result.coords[i] %= coords1[i%N];
  return result;
}

Ces surcharges sont entourées d'une définition de classe Template:

template <class T_COORDS, size_t C_COORDS, size_t N_COORDS>
class Coords {
public:

  T_COORDS coords[C_COORDS*N_COORDS];

  // (body in here)

};
0
Ismael Harun 30 mai 2020 à 11:46

3 réponses

Meilleure réponse

T_COORDS est un paramètre de modèle de classe, pas un paramètre de modèle de fonction, ce qui signifie qu'il ne fait aucune différence pour le tri partiel car la fonction plus générale est instanciée avec T_COORDS=float de toute façon, et donc exactement la même chose que { {X2}} un. Vous pouvez cependant désactiver cette fonction à partir de la résolution de surcharge, en utilisant le fait qu'elle a déjà des conditions enable_if qui dépendent du contexte immédiat:

template <std::size_t N
        , std::enable_if_t<N != 0 && N <= C_COORDS*N_COORDS && N % C_COORDS == 0
                           && !std::is_same<T_COORDS, float>{}
                           // ~~~~~~~~~~~~^
        , bool> = false>
friend Coords operator %(const Coords<T_COORDS, C_COORDS, N_COORDS>& coords0
                       , const auto (& coords1)[N]);
0
Piotr Skotnicki 30 mai 2020 à 09:49

Je garderais juste une de ces surcharges mais changerais sa boucle for en ceci:

for (int i=0; i < C_COORDS*N_COORDS; i++)
    result.coords[i] = my_mod(result.coords[i], coords1[i%N]);

Après avoir défini my_mod comme ceci (dans la portée externe):

template <typename T>
T my_mod(const T& x, const T& y) { return x % y; }

float my_mod(float x, float y) { return fmod(x, y); }
// maybe define it for double as well
0
John Zwinck 30 mai 2020 à 12:19

Je n'ai pas compris votre logique, mais si vous voulez faire changer le comportement de votre fonction sur le type double ou non, vous pouvez utiliser quelque chose comme ce qui suit.

#include <type_traits>
#include <iostream>
template <class T>
void func(){
    constexpr static bool isFloat = std::is_floating_point<T>::value;//static in classes
    if (isFloat) std::cout << "f\n";//u can use fmod() here
    else std::cout << "i\n";//use regular % here
}
int main(){
    func<int>();
    func<double>();
}
0
asmmo 30 mai 2020 à 10:18
62100020