2

donc I've written an answer qui utilise une fonction pour sélectionner le type sans canevas d'objet.Comment puis-je éviter Explicitement Spécialiste des fonctions de recherche avec l'argument sans canevas charge

J'ai défini les types:

struct pt { 
    double t; 
    double e; 
    double c_vis; 
    double c_invis; 
}; 

struct pt_weighted : pt { 
    double sigma; 
}; 

Et ma fonction ressemble sans canevas:

template <typename T> 
void foo() { 
    for(T point; dataFile >> point;) { 
     set.curve.push_back(point); // store point 

     data_numPoints++; // collect some stats 
     set.curveAvg += point.e;    
    } 
} 

Étant donné que minimizator_weighted décide quel type à utiliser lors de l'exécution, j'appelle foo avec:

minimizator_weighted ? foo<data_set::pt_weighted>() : foo<data_set::pt>(); 

Richard Hodges is suggesting en utilisant Argument Dependent Lookup (ADL) pour éviter les "fonctions de modèle explicitement spécialisées". Je ne suis pas sûr de ce qu'il veut dire alors j'ai pensé que j'ouvrirais une nouvelle question afin que lui ou quelqu'un puisse expliquer plus loin dans une réponse.

Répondre

1

Dans l'exemple ci-dessous, vous n'avez pas besoin de spécifier le type de points que vous serez en train de lire. Au lieu, le compilateur peut comprendre que par l'argument que vous avez passé dans la fonction. (NOTE:. Ce bloc de code suppose que set, dataFile et data_numPoints sont accessibles et modifiables à partir de la fonction)

template<class T> 
void foo(T point) { 
    while (dataFile >> point) { 
     set.curve.push_back(point); 
     data_numPoints++; 
     set.curveAvg += point.e; 
    } 
} 

Maintenant, pour l'appeler, vous venez de passer dans une instance du type que vous aimez sur.

void bar() { 
    foo(data_set::pt()); // builds unweighted data set 
    foo(data_set::pt_weighted()); // builds weighted data set 
} 
0

Si vous voulez une déduction d'argument de modèle, vous devez la déduire de quelque chose. Par exemple, vous pouvez déduire un paramètre de modèle de ses arguments. Par exemple, vous pouvez changer votre fonction à ceci:

template <typename T> 
void foo(T p) { 
    for(T point = p; dataFile >> point;) { 
     set.curve.push_back(point); // store point 

     data_numPoints++; // collect some stats 
     set.curveAvg += point.e;    
    } 
} 

Quand vous appelez votre fonction, vous pouvez déduire comme ceci:

data_set::pt_weighted ptw; 
data_set::pt pt; 

minimizator_weighted ? foo(ptw) : foo(pt); 
3

quelque chose le long de ces lignes.

Notez que je peux maintenant ajouter un nouveau type de point (ou tapez set) sans changer la logique dans plus d'une fonction. Tout ce que j'ai à faire est de fournir des surcharges ADL de operator>> et do_something pour les nouveaux types.

Donc, ma logique de base est maintenant séparé des détails de mise en œuvre de chaque type de jeu/type de point. Si je veux utiliser les mêmes points de code dans un autre système de coordonnées, j'ai moins de code à changer (dans un vrai projet).

#include <iostream> 
#include <vector> 

struct pt { 
    double t; 
    double e; 
    double c_vis; 
    double c_invis; 
}; 
std::istream& operator>>(std::istream& is, pt& p) 
{ 
    p.c_vis = 0; 
    p.c_invis = 0; 
    return is >> p.t >> p.e; 
} 

struct pt_weighted : pt { 
    double sigma; 
}; 

std::istream& operator>>(std::istream& is, pt_weighted& p) 
{ 
    auto sigma_correction = [](double& sigma) { 
     // whatever this is supposed to do; 
    }; 
    is >> static_cast<pt&>(p) >> p.sigma; 
    sigma_correction(p.e); 
    return is; 
} 


template<class Point> struct set 
{ 
    using point_type = Point; // the type name point_type is now part of the set's type interface, so I can use it in dependent code. 
    std::vector<point_type> points; 
}; 

using pt_set = set<pt>; 
using pt_weighted_set = set<pt_weighted>; 


// 
// one implementation of read logic, for all set types. 
// 
template<class SetType> 
void read_set(std::istream& is, SetType& target) 
{ 
    while(is) { 
    // using the type protocol here 
    auto point = typename SetType::point_type(); // or target.makePoint() ? 
    is >> point; 
    target.points.push_back(std::move(point));  
    } 
} 

extern void do_something(pt_set&); 
extern void do_something(pt_weighted_set&); 

void operation(std::istream& is) 
{ 
    extern bool useSigma(); 

    // even these lines now no longer need to be repeated 
    auto perform = [](auto&& myset) { 
    read_set(is, myset); 
    do_something(myset); 
    }; 

    if (useSigma()) 
    { 
    perform(pt_weighted_set()); 
    } 
//else if (someOtherCondition()) { 
// perform(someOtherSetType()); 
//} 
    else { 
    perform(pt_set()); 
    } 
};