0

我花了一段时间才弄清楚这一点,但语义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::anyvoid*. 指针,指针,混合了一些类型安全。基本上我想要的是boost::any_pointer,或类似的东西。有没有办法禁止boost::any接受除指针以外的任何东西?如果没有,是否有替代方案boost::any可以为我提供我正在寻找的语义?

4

3 回答 3

2

您使用 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/any和http://en.cppreference.com/w/cpp/experimental/any/any_cast

于 2016-06-13T20:20:39.593 回答
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_iftype trait 在 C++11 中可用,但也可以在 boost 中找到。这就是将您限制MyAny为仅指针类型的原因。

于 2016-06-13T20:19:04.537 回答
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要求我先收集足够的分数,所以......

于 2019-10-18T12:59:46.860 回答