2

因此I've written an answer它使用模板化函數來選擇對象類型。如何避免明確專用模板化函數使用參數依賴查找

我定義的類型:

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

struct pt_weighted : pt { 
    double sigma; 
}; 

我的模板化的功能是這樣的:

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;    
    } 
} 

鑑於minimizator_weighted決定在運行時使用哪種類型的,我稱之爲foo有:

​​

Richard Hodges is suggesting使用Argument Dependent Lookup (ADL)以避免「顯式專門的模板功能」。我只是不確定他的意思,所以我想我會開一個新的問題,以便他或某人可以在答案中進一步解釋。

回答

1

在下面的示例中,您不需要指定要讀入的點的類型,而是編譯器可以通過傳入該函數的參數來計算出結果。 (注:此代碼塊假定setdataFile,並data_numPoints是從函數中訪問和可變)

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

現在,調用它,你只是通過在你關心的類型的實例關於。

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

如果你想要模板參數推導,你必須從某些事情推論出來。例如,你可以從它的參數中推導一個函數模板參數。例如,你可以改變你的函數是:

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;    
    } 
} 

然後當你打電話給你的功能,你可以推斷出它是這樣的:

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

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

東西沿着這些路線。

請注意,現在我可以添加新的點類型(或設置類型),而不必在多個函數中更改邏輯。我所要做的就是爲新類型提供ADL過載operator>>do_something

因此,我的核心邏輯現在與每個集合類型/點類型的實現細節分開。如果我想在其他座標系統中使用相同的代碼點,我就不需要更改代碼(在實際項目中)。

#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()); 
    } 
}; 
相關問題