boost::any 混淆指针与值
boost::any confusion with pointers vs values
我花了一段时间才弄明白,但是 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);
在这种情况下,我必须取消引用 return 值,因为 boost::any_cast
returns int**
!我也没有检查过,但我认为如果 something.empty() == true
这可能会崩溃。这一点都不简单。
我不想在我的 boost::any
中存储值,我希望它只对指针起作用并且在语义上更接近 void*
。指针输入,指针输出,混合了一些类型安全。本质上我想要的是 boost::any_pointer
或类似的东西。有没有办法禁止 boost::any
接受指针以外的任何东西?如果没有,是否有 boost::any
的替代方案可以提供我正在寻找的语义?
注意:我假设您想将指针存储在 boost::any
中,因为您正在寻找 boost::any_pointer
中的内容(尽管不是-存在)。
boost::any_cast
returns 指向存储在其中的实际值的指针(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
限制为仅指针类型的原因。
您使用的 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 and http://en.cppreference.com/w/cpp/experimental/any/any_cast
虽然这是一个很老的问题,但我还是想指出一个简单的误解 [我认为] 在问题的前言中:
int value = 100;
boost::any something;
something = &value; // 1)
//...later...
int* value = *boost::any_cast<int*>(&something); // 2)
1) 这节省了 "int *" 的东西。
2) 这主要包含几个步骤:
- "&something" 获取某物的地址,即 return "boost::any *"
- "boost::any_cast()" 现在将此地址转换为指向 int 的指针 - 这可能不是 void.pointer 想要的。而且我不知道是否 - 如果,为什么 - 这似乎有效。
- 然后取消对“*boost::...”的引用,即再次取消第一步中的“&”。
我想,void.pointer 想在这里做的,更多的是沿着以下路线:
int* value = boost::any_cast<int*>(something);
.
PS:我本来想把它放在一个简单的评论中,而不是一个完整的答案 - 但是 Whosebug 要求我先收集足够的点数,所以...
我花了一段时间才弄明白,但是 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);
在这种情况下,我必须取消引用 return 值,因为 boost::any_cast
returns int**
!我也没有检查过,但我认为如果 something.empty() == true
这可能会崩溃。这一点都不简单。
我不想在我的 boost::any
中存储值,我希望它只对指针起作用并且在语义上更接近 void*
。指针输入,指针输出,混合了一些类型安全。本质上我想要的是 boost::any_pointer
或类似的东西。有没有办法禁止 boost::any
接受指针以外的任何东西?如果没有,是否有 boost::any
的替代方案可以提供我正在寻找的语义?
注意:我假设您想将指针存储在 boost::any
中,因为您正在寻找 boost::any_pointer
中的内容(尽管不是-存在)。
boost::any_cast
returns 指向存储在其中的实际值的指针(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
限制为仅指针类型的原因。
您使用的 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 and http://en.cppreference.com/w/cpp/experimental/any/any_cast
虽然这是一个很老的问题,但我还是想指出一个简单的误解 [我认为] 在问题的前言中:
int value = 100;
boost::any something;
something = &value; // 1)
//...later...
int* value = *boost::any_cast<int*>(&something); // 2)
1) 这节省了 "int *" 的东西。
2) 这主要包含几个步骤:
- "&something" 获取某物的地址,即 return "boost::any *"
- "boost::any_cast()" 现在将此地址转换为指向 int 的指针 - 这可能不是 void.pointer 想要的。而且我不知道是否 - 如果,为什么 - 这似乎有效。
- 然后取消对“*boost::...”的引用,即再次取消第一步中的“&”。
我想,void.pointer 想在这里做的,更多的是沿着以下路线:
int* value = boost::any_cast<int*>(something);
.
PS:我本来想把它放在一个简单的评论中,而不是一个完整的答案 - 但是 Whosebug 要求我先收集足够的点数,所以...