2016-12-29 23 views
3

我有一個與std::mapshared_ptr<T>,我需要它以使用實際值T類型,即*key的)進行查找,共享指針本身的不值。是否有std :: set(或std :: map)與shared_ptr鍵提供基於價值的查找比較器? std :: owner_less究竟做了什麼?

我知道我可以編寫自己的自定義比較器(正如我在下面所做的那樣),但是我想知道STL是否專門爲此提供了比較器。

爲了證明什麼,我說什麼,我創建了一個使用字符串std::set這個簡單的例子(我也把它on GitHub as a gist):

#include <set> 
#include <string> 
#include <memory> 
#include <iostream> 
#include <functional> 

template< typename T > 
struct shared_ptr_comparator { 
    bool operator()(const std::shared_ptr<T> &a, const std::shared_ptr<T> &b) const { 
    return std::less<T>()(*a, *b); 
    } 
}; 

void ptr_set_with_custom_comparator() { 
    std::set< std::shared_ptr<std::string>, shared_ptr_comparator<std::string> > ptr_set; 

    ptr_set.insert(std::make_shared<std::string>("world")); 
    ptr_set.insert(std::make_shared<std::string>("hello")); 
    ptr_set.insert(std::make_shared<std::string>("abc")); 

    for(auto const& entry : ptr_set) { 
     std::cout << *entry << std::endl; 
    } 
} 

void ptr_set_with_owner_less() { 
    std::set< std::shared_ptr<std::string>, std::owner_less<std::shared_ptr<std::string>> > ptr_set; 

    ptr_set.insert(std::make_shared<std::string>("world")); 
    ptr_set.insert(std::make_shared<std::string>("hello")); 
    ptr_set.insert(std::make_shared<std::string>("abc")); 

    for(auto const& entry : ptr_set) { 
     std::cout << *entry << std::endl; 
    } 
} 

void raw_set() { 
    std::set<std::string> raw_set; 

    raw_set.insert("world"); 
    raw_set.insert("hello"); 
    raw_set.insert("abc"); 

    for(auto const& entry : raw_set) { 
     std::cout << entry << std::endl; 
    } 
} 

int main() { 
    std::cout << "A basic set of strings:" << std::endl; 
    raw_set(); 
    std::cout << std::endl; 

    std::cout << "A set of shared_ptr<string>s with owner_less as the comparator:" << std::endl; 
    ptr_set_with_owner_less(); 
    std::cout << std::endl; 

    std::cout << "A set of shared_ptr<string>s with the comparator shared_ptr_comparator:" << std::endl; 
    ptr_set_with_custom_comparator(); 

    return 0; 
} 

上面的代碼可以用clang++ -Wall -std=c++11得到遵守。迭代和打印內容std::set

A basic set of strings: 
abc 
hello 
world 

A set of shared_ptr<string>s with owner_less as the comparator: 
world 
hello 
abc 

A set of shared_ptr<string>s with the comparator shared_ptr_comparator: 
abc 
hello 
world 

這裏,排序順序意味着_actual基礎值)被比較:這裏的輸出。上面的例子中的快速概覽:

  • 功能raw_set只是使用set<string>(不使用shared_ptr),並且存在以供參考。

  • 我能用手寫的shared_ptr_comparator實現我想要的。使用它的功能ptr_set_with_custom_comparator按預期工作。

  • 功能ptr_set_with_owner_less未按預期工作。 owner_less(或owner_before)是否依賴指針本身的地址/值?

我有兩個問題:

  • 做任何事情相當於shared_ptr_comparator,存在於STL(在上面的程序中定義)?我問,因爲我編寫的比較程序似乎是一個非常常見的用例,如果STL沒有任何等價物,我會感到非常驚訝。

  • owner_lessowner_before(它稱之爲)是做什麼的?他們只是檢查底層指針的等價性嗎?我不確定我是否正確使用它。

在此先感謝您對此問題的任何答案。

+0

您*仔細閱讀了標準C++ [容器](http://en.cppreference.com/w/cpp/container)的相關文檔嗎? –

回答

3

在STL中是否存在與shared_ptr_comparator(在上述程序中定義)等價的東西?我問,因爲我編寫的比較程序似乎是一個非常常見的用例,如果STL沒有任何等價物,我會感到非常驚訝。

我也很驚訝,但不,STL沒有內置比較器指針的工作方式。但是有更好的方法來實現它,它允許傳遞任何指針。

template<typename T, typename comp_t> 
bool ptr_compare(T lhs, T rhs, comp_t comp) { 
    return comp(*lhs, *rhs); 
} 

你可以調用它的方法:

ptr_compare(a_ptr, b_ptr, std::less<int>()) 

如果你想用STL容器兼容的版本:

template<typename T> 
bool ptr_less(T lhs, T rhs) { 
    return std::less<decltype(*lhs)>()(*lhs, *rhs); 
} 

究竟做owner_less和owner_before(它電話)呢?他們只是檢查底層指針的等價性嗎?我不確定我是否正確使用它。

std::owner_less不按價值進行比較,而是由所有者進行比較,因此與您的問題無關。

std::shared_ptr<T>::owner_beforestd::owner_less調用以找出排序。

+0

謝謝!只是簡單的說明:'ptr_compare'是一個很好的概括,但我不認爲它可以作爲STL容器比較器,因爲他們期望只有兩個參數('lhs'和'rhs')的仿函數。你可以避開上面的'comp_t comp',它可以和STL容器一起工作。 –

+0

對,我編輯了答案並添加了與STL容器一起使用的示例ptr_less。 –

+0

只是好奇,'owner_less'的用例究竟是什麼?而且,它的排序是基於什麼? (它的指針地址的數字值?) –

相關問題