2016-11-16 91 views
3

我想用下面的模板成員函數C++ 11:創建一個函數總是返回true,使用的函數參數

template <typename Entity> 
class SomeCollection 
{ 
    // .... 

    template <typename Measure, typename Filter> 
    Entity maximalEntity(Measure&& measure, Filter&& requirement) 
    { 
     auto maxEntity = Entity(); 
     auto maxValue = -std::numeric_limits<double>::infinity(); 

     for (auto ent /* some iteration method*/) 
     { 
      auto measurement = measure(ent); 
      if (requirement(ent) && measurement > maxValue) 
       std::tie(maxEntity, maxValue) = std::make_tuple { ent, measurement }; 
     } 
     return maxEntity; 
    } 

    // ... 
}; 

什麼是調用從客戶這個功能最好的辦法最簡單的方法沒有過濾器要求的代碼(只有最大元素)?

我能想出是最好的:

class Something; 
double measure(Something&); 
SomeCollection<Something> collection; 

auto maximum = collection.maximalEntity(measure, [](const Something&) { return true; }); 

,但我想這個lambda函數可以改善沒有?

回答

8

不知道拉姆達如何能改善,但你可以定義給出任何輸入總是返回true(這也可以在這裏使用)的通用拉姆達:

auto always_true = [](auto&&...) { return true; }; 

,你會使用它爲:

auto maximum = collection.maximalEntity(measure, always_true); 

Live demo


爲C++ 11的等效實現如下:

struct always_true { 
    template<typename... Args> 
    bool operator()(Args&&...) const noexcept { 
     return true; 
    } 
}; 

這將被用來作爲:

auto maximum = collection.maximalEntity(measure, always_true{}); 

Live demo

+1

偉大的答案。只是挑剔(或者可能是風格問題):在C++ 11版本中,您可以創建'struct always_true_t',然後'const always_true_t always_true' – bolov

2

您可以創建一個lambda返回true,並設置它作爲默認參數。

auto true_filter = [](const Something& arg){ return true; }; 
//auto true_filter = [](auto&& arg){ return true; }; if you have c++14 
... 

template <typename Measure, typename Filter = decltype(true_filter)> 
Entity maximalEntity(Measure&& measure, Filter requirement = true_filter) 
{ 

... 
auto maximum = collection.maximalEntity(measure); 

注意FilterFilter&&改變。我還沒有得到它與rvalue參考這裏工作。

雖然明確表示可能是更好的設計。只是一個選項,它 「短」

+0

多態lambda被添加到C++ 14中,問題被標記爲C++ 11 。你無法使用右值引用的原因是你將'always_true'定義爲左值。如果將默認模板參數設置爲左值ref,則「Filter &&」將起作用,即「decltype(true_filter)&' –

1

C++ 14:

template<class T> 
auto always() { 
    return [](auto&&...)->T{return {};}; 
}; 

或C++ 11:

template<class T> 
struct always { 
    template<class...Args> 
    T operator()(Args&&...)const{ return {}; } 
}; 

使用:

collection.maximalEntity(measure, always<std::true_type>()); 

這有所涉及的lambda的真實性在類型系統中被編碼的優點,這使編譯器能夠更輕鬆地優化其行爲。

這也讓你做always<std::false_type>always<std::integral_constant<int, 42>>()

在C++ 17我會做:(?也許always<nullptr>()

template<auto x> 
auto always() { 
    return [](auto&&)->std::integral_constant<decltype(x), x> 
    { return {}; }; 
} 

允許always<true>()always<42>()