2015-12-21 42 views
9

也許我不是第一個發現std::exception_ptr可以用來實現any類型(性能考慮被擱置)的第一人,因爲它可能是C++中唯一可以使用的類型抱什麼。但是,谷歌搜索沒有在這個方向上帶來任何結果。std :: any std :: exception_ptr

有誰知道以下方法是否在任何有用的地方使用過?

#include <exception> 
#include <iostream> 

struct WrongTypeError : std::exception { }; 

class Any { 
public: 
    template <class T> 
    void set (T t) { 
     try { throw t; } 
     catch (...) { m_contained = std::current_exception(); } 
    } 

    template <class T> 
    T const & get() { 
     try { std::rethrow_exception (m_contained); } 
     catch (T const & t) { return t; } 
     catch (...) { throw WrongTypeError {}; } 
    } 

private: 
    std::exception_ptr m_contained = nullptr; 
}; 

int main() { 
    auto a = Any {}; 
    a.set (7); 
    std::cout << a.get<int>() << std::endl; 

    a.set (std::string {"Wonderful weather today"}); 
    std::cout << a.get<std::string>() << std::endl; 
    return 0; 
} 
+0

我編輯了代碼。我認爲它不再分割。 – JohnB

+0

g ++ 4.8.4不會產生一千萬個'Any'並將它們存儲在'vector'中。然而,它非常緩慢。 (30秒設置並獲得1000萬個值)。 – JohnB

+1

實際上,我一直認爲更好的技巧(因爲它自C++ 98開始可用)將使用'std :: locale',存儲任何你想要的作爲一個方面。 –

回答

5

,因爲它可能是在C++中唯一的類型,可以容納任何東西。

恐怕情況並非如此。 boost :: any可以保存任何類型,甚至可以拷貝(假設類型是可複製的)。它的實現(廣義上)使用一個基類和模板孩子:

class any_base { 
    ... 
} 

template <class T> 
class any_holder : public any_base 
{ 
private: 
    T m_data; 
} 

由此你可以想象,你可以的東西任何類型爲any_holder(用正確的接口),然後就可以持有any_holder指向any_base的指針。這種技術是一種類型的刪除;一旦我們有了一個any_base指針,我們就擁有一個對象,但不知道類型。你可以說這是完全類型的擦除,像std :: function提供了部分類型的擦除(並且可能使用類似的技術,我不確定是否在頭頂)。

boost :: any提供了額外的接口來支持其持有任何類型的使用,它可能提供更好的性能,因爲拋出異常是瘋狂的慢。另外,正如我之前提到的,它正確地複製了底層對象,這非常酷。 exception_ptr是一個共享所有者指針,所以我相信它會生成淺拷貝。

升壓任何網站:http://www.boost.org/doc/libs/1_59_0/doc/html/any.html

它正在考慮,我相信標準:http://en.cppreference.com/w/cpp/experimental/any

這似乎是實現類似於提高,但增加了一個小的目標優化。

exception_ptr是一個非常奇怪的野獸,據我所知,我以前遇到過它,並且搜索了它,並且出現了令人驚訝的很少的信息。我很確定它是不可思議的,即它不能在用戶空間中實現。我這樣說是因爲當你扔它時,這種類型似乎魔法般地自我消除,這通常是不可能的。

+0

這就是我爲什麼創建了我的'任何',儘管實際上這個機制很簡單,只需要一個void *和一個const type_info&就可以實現,但是如果你想要正確的清理,你必須存儲析構函數。 – stellarpower

3

你肯定是我遇到過的第一個想到它的人。

我肯定你的橫向思維能力:)

沒有與然而這種方法有問題,(不是明顯的性能問題等)印象深刻。

這源於throw允許複製拋出的對象。首先,這會限制你可能存儲在你的'任何'類中的內容,其次它會有進一步的性能影響,第三,每次你訪問你的對象時,編譯器都沒有義務給你同一個對象。它可以給你一個副本。這意味着至少你應該只以這種方式存儲不可變的對象。 (注意:當我說'應該'時,我的意思是'絕對不應該!'):)

你可以通過製作一個分配內存來存儲對象的類,記錄它的類型並正確刪除它來解決這個問題......但是如果你這樣做了,你會更好,沒有異常複雜無論如何。

在任何情況下,這都是boost :: any所涵蓋的內容。

+1

「我對你的橫向思維能力印象深刻」 - 我不能兩次對上,我可以嗎? – JohnB

相關問題