boost ::任何与指针和值

时间:2016-06-13 19:56:20

标签: c++ boost boost-any

我花了一些时间才弄明白这一点,但boost::any的语义令人困惑。

使用值类型,您可以这样使用它:

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

此代码清晰明了,但在内部存储value作为副本。这意味着对于我放在boost::any内的较大对象,它们将被复制。我用这个替换void*的任何函数都会期望在我修改boost::any对象中包含的值时修改函数外部的值(因为它复制了它所以不会发生) )。

因此,如果我将指针放入其中,事情会变得奇怪:

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

在这种情况下我必须取消引用返回值,因为boost::any_cast返回int**!我还没有检查,但我认为如果something.empty() == true可能会崩溃。这根本不是直截了当的。

我不想在我的boost::any中存储值,我希望它只能在指针上运行,并且在语义上更接近void*。指针,指针,有一些类型安全混合。基本上我想要的是boost::any_pointer,或类似的东西。有没有办法禁止boost::any接受指针以外的任何东西?如果没有,是否有boost::any的替代品可以为我提供我正在寻找的语义?

3 个答案:

答案 0 :(得分:1)

注意:我假设您要在boost::any中存储指针,因为您正在查找boost::any_pointer行(虽然不存在)。< / p>

boost::any_cast返回指向存储在其中的实际值的指针(holder中的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 :(得分:1)

您正在使用any_cast错误:

基本上有两种(三种)口味。

  • 引用任何并返回值或对内容的引用
  • 将指针指向any并返回指向内容的指针

示例:

#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

答案 2 :(得分:0)

尽管这是一个很老的问题,但我还是想在提出的问题的序言中指出一个简单的误解[我认为]:

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

1)这样可以将“ int *”保存在某些内容中。

2)这实际上包含几个步骤:

  • “&something”获取某物的地址,即返回“ boost :: any *”
  • “ boost :: any_cast()”现在将此地址转换为指向int的指针-这可能不是void.pointer想要的。而且我不知道这是否可行,以及是否可行。
  • 然后取消引用“ * boost :: ...”,即再次从第一步取消“&”。

void.pointer我想在这里做的事情,大致如下:

int* value = boost::any_cast<int*>(something);

PS:我希望将其放在一个简单的注释中,而不是一个完整的答案-但是stackoverflow要求我首先收集足够的分数,所以...