2016-06-13 50 views
0

我花了一段時間才弄清楚這一點,但boost::any的語義很混亂。boost ::任何指針與值的混淆

對於值類型,您可以使用它像這樣:

int value = 100; 
boost::any something; 
something = value; 
//...later... 
int value = boost::any_cast<int>(&something); 

此代碼是明確的,是有道理的,但商店value內部的一個副本。這意味着我放置在boost::any內的較大物體將被複制。當我修改boost::any對象中包含的值(因爲它複製它而不會發生)時,我用其替換void*的任何函數都會預期修改函數外部的值。

所以,如果我把球進去,事情就變得怪異:

​​

我要提領返回值在這種情況下,因爲boost::any_cast回報int**!我也沒有檢查,但我認爲這可能會崩潰,如果something.empty() == true。這根本不是直截了當的。

我不想將值存儲在我的boost::any中,我希望它只能在指針上運行,並且在語義上接近void*。指針指出,與一些類型安全混合在一起。基本上我想要的是boost::any_pointer,或類似的東西。有沒有辦法阻止boost::any接受除指針之外的任何內容?如果沒有,是否有替代boost::any,可以給我我正在尋找的語義?

+0

'boost :: any' is pretty e asy來創建,然後你可以改變你認爲合適的語義。 –

+0

你的第一個片段不起作用,需要解引用(如snippet2)[Demo](http://coliru.stacked-crooked.com/a/df5bdb307f56b709) – Jarod42

+0

你仍然可以將'boost :: any'包裝到類中只允許指針。 – Jarod42

回答

1

注意:我假設你想存儲指針在boost::any,因爲你正在尋找對boost::any_pointer線的東西(雖然不存在)。

boost::any_cast將指針返回存儲在其中的實際值(held對象內部持有者)。因此,除非您確實想稍後複製它,否則它會保存副本。

template<typename ValueType> 
    ValueType * any_cast(any * operand) BOOST_NOEXCEPT 
    { 
     return operand && operand->type() == boost::typeindex::type_id<ValueType>() 
      ? &static_cast<any::holder<BOOST_DEDUCED_TYPENAME remove_cv<ValueType>::type> *>(operand->content)->held 
      : 0; 
    } 

你總是可以創造約boost::any的包裝只允許指針類型:

class MyAny { 
public: 
    template <typename T, 
     typename = typename std::enable_if<std::is_pointer<std::remove_cv<T>::type>::value>::type> 
    MyAny(T ptr): any_(ptr) {} 

template <typename ValueType> 
ValueType operator*() { 
    return *boost::any_cast<ValueType>(&any_); 
} 

private: 
    boost::any any_ 
}; 

上面是一個粗略的代碼,我沒有編譯和測試它。

std::enable_if類型特徵在C++ 11中可用,但也可以在boost中找到。這就是將你的MyAny限制爲僅指針類型。

1

您正在使用any_cast錯誤:

基本上有兩(三)種口味。

  • 以到任何一個參考和一個值或參考返回到內容
  • 以一個指向任何和返回指針到內容

實例:

#include <boost/any.hpp> 
int main() 
{ 
    // Any holding a value 
    { 
     boost::any any_value(1); 
     // Throws bad_any_cast if the content is not 'int' (in this case): 
     int value = boost::any_cast<int>(any_value); 
     // Throws bad_any_cast if the content is not 'int' (in this case): 
     int& reference = boost::any_cast<int&>(any_value); 
     // Returns a null pointer if the content is not 'int' (in this case): 
     int* pointer = boost::any_cast<int>(&any_value); 
    } 

    // Any holding a pointer (which is nothing else but a value) 
    { 
     int integer = 0; 
     boost::any any_ptr(&integer); 
     // Throws bad_any_cast if the content is not 'int*' (in this case): 
     int * pointer = boost::any_cast<int*>(any_ptr); 
     // Throws bad_any_cast if the content is not 'int*' (in this case): 
     int*& pointer_reference = boost::any_cast<int*&>(any_ptr); 
     // Returns a null pointer if the content is not 'int*' (in this case): 
     int** pointer_pointer = boost::any_cast<int*>(&any_ptr); 
    } 
} 

另請參閱:http://en.cppreference.com/w/cpp/experimental/anyhttp://en.cppreference.com/w/cpp/experimental/any/any_cast

+0

我看到語法拋出了很多人。雖然對於std :: any是一樣的。 –

+0

我試圖避免使用'boost :: any'的異常,這就是爲什麼我使用指針超載的原因。你的第一個和第二個例子好像會拋出異常;至少在我的測試中它確實如此。 –

+0

這裏是我寫的一個示例,顯示它拋出;我不希望它拋出,我想要一個'nullptr'返回如果類型是錯誤的:http://coliru.stacked-crooked.com/a/f6ffdf4387e335d6 –