[英]Why doesn't const_cast work on arguments to std::function?
I'm providing a const and non-const variation of a member function where I reuse the const version to implement the non-const version as described in this answer per Scott Meyers books. 我正在提供成员函数的const和非const变体,其中我重用const版本来实现非const版本, 如本答案中所描述的每个Scott Meyers书籍。
The const version takes an argument of type: const版本采用类型的参数:
const std::function< void (const Foo &) > &
vs the non-const takes an argument of type: vs非const采用类型的参数:
const std::function< void ( Foo &) > &
In the implementation, I have to use reinterpret_cast
because const_cast
is not working. 在实现中,我必须使用
reinterpret_cast
因为const_cast
不起作用。
Eg,: 例如,:
const std::function< void (Foo &) > & Processor;
reinterpret_cast< const std::function< void (const Foo &) > & >( Processor );
vs VS
const std::function< void (Foo &) > & Processor;
const_cast< const std::function< void (const Foo &) > & >( Processor );
Wouldn't this be in the spirit of what const_cast
is meant for? 这不符合
const_cast
的意思吗? Is this just an oversight in the language definition to perhaps be fixed in C++2x or would const_cast
never be in the spirit of things here? 这只是对语言定义的疏忽,或许可以在C ++ 2x中修复,或者
const_cast
永远不会符合这里的精神?
Here is more complete code: 这是更完整的代码:
void Collection::ProcessCollection(const std::function< void (const Foo &) > & Processor) const
{
for( int idx = -1 ; ++idx < m_LocalLimit ; )
{
if ( m_Data[ idx ] )
{
Processor( m_Data[idx] );
}
}
const int overflowSize = OverflowSize();
for( int idx = -1 ; ++idx < overflowSize ; )
{
Processor( (*m_Overflow)[ idx ] );
}
}
void Collection::ProcessCollection(const std::function< void (Foo &) > & Processor)
{
const Collection * constThis = const_cast< const Collection * >( this );
const std::function< void (const Foo &) > & constProcessor
= reinterpret_cast< const std::function< void (const Foo &) > & >( Processor );
constThis->ProcessCollection( constProcessor );
}
Generally speaking, it's not safe to use const_cast
to cast away const
ness that appears in template arguments. 一般来说,使用
const_cast
来抛弃模板参数中出现的const
是不安全的。 For example, consider this (admittedly, somewhat contrived) code: 例如,考虑这个(诚然,有些人为的)代码:
template <typename T> struct Wrapper {
int x;
};
template <> struct Wrapper<char *> {
double y;
};
Here, a pointer to a Wrapper<const char *>
points to a very different object than a Wrapper<char *>
, so doing a const_cast
to turn a Wrapper<const char *> *
into a Wrapper<char *> *
would result in a pointer to a struct
containing an int
now pointing at a struct
containing a double
, breaking some language rule whose name eludes me at the moment. 在这里,一个指向
Wrapper<const char *>
指向一个非常不同的对象比Wrapper<char *>
所以做了const_cast
把一个Wrapper<const char *> *
成Wrapper<char *> *
将导致在一个指向struct
的指针中,该struct
包含一个int
现在指向一个包含double
的struct
,打破了一些语言规则,其名称目前不在我身上。 :-) :-)
Since in general it's not safe to const_cast
this way, the language spec doesn't allow for const_cast
to be used like this, which is why in your case, even though the operation makes intuitive sense, the language disallows your code with const_cast
. 因为一般来说
const_cast
这种方式不安全,语言规范不允许像这样使用const_cast
,这就是为什么在你的情况下,即使操作直观,语言也不允许使用const_cast
代码。
I am fairly certain that using a reinterpret_cast
here leads to undefined behavior, since the language considers std::function<T1>
and std::function<T2>
to be different, incompatible types when T1
and T2
aren't the same. 我相当肯定在这里使用
reinterpret_cast
会导致未定义的行为,因为语言认为std::function<T1>
和std::function<T2>
是不同的,当T1
和T2
不相同时,不兼容的类型。 It may happen to work on your system by pure coincidence, but I don't believe you can safely assume this will work. 它可能恰巧在您的系统上运行纯粹巧合,但我不相信您可以安全地认为这将起作用。
reinterpret_cast
here is undefined behavior. reinterpret_cast
这里是未定义的行为。 const_cast
isn't appropriate, because the const
ness of template parameters isn't something you can cast away. const_cast
不合适,因为模板参数的const
不是你可以抛弃的东西。
The easy way to solve this is, well, don't. 解决这个问题的简单方法是,不要这样做。 Get rid of some references.
摆脱一些参考。 Swap who implements it.
交换谁实现它。
void Collection::ProcessCollection(std::function< void (const Foo &) > Processor) const
{
Collection * mutableThis = const_cast< Collection * >( this );
mutableThis->ProcessCollection( Processor );
}
void Collection::ProcessCollection(std::function< void (Foo &) > Processor)
{
for( int idx = -1 ; ++idx < m_LocalLimit ; )
{
if ( m_Data[ idx ] )
{
Processor( m_Data[idx] );
}
}
const int overflowSize = OverflowSize();
for( int idx = -1 ; ++idx < overflowSize ; )
{
Processor( (*m_Overflow)[ idx ] );
}
}
std::function
stores things that are call-compatible with it. std::function
存储与它调用兼容的东西。
If you take a Foo&
, you can call a function expecting a Foo const&
with it. 如果你选择
Foo&
,你可以调用一个期望Foo const&
它的Foo const&
。 So you can store a std::function<void(Foo const&)>
within a std::function<void(Foo&)>
. 所以你可以在
std::function<void(Foo const&)>
存储一个std::function<void(Foo const&)>
std::function<void(Foo&)>
。
Wrapping something in a std::function
can involve allocating. 在
std::function
包装内容可能涉及分配。 So you may want to find a high-quality function_view<Sig>
to replace your use of std::function
. 因此,您可能希望找到一个高质量的
function_view<Sig>
来替换您对std::function
。
In another comment, you state that this code is in a critical loop. 在另一条评论中,您声明此代码处于关键循环中。 Eliminating
std::function
entirely is a good move, or at least reducing the type erasure taps and passing batches of data to it somehow. 完全消除
std::function
是一个很好的举动,或者至少减少类型擦除点击并以某种方式将批量数据传递给它。
The inversion of const/unconst is still appropriate; const / unest的反转仍然是合适的; we implement const in terms of mutable instead of mutable in terms of const because one is a covariant operation, the other is a contravariant operation.
我们用const表示const而不是const的变量,因为一个是协变运算,另一个是逆变运算。 See here .
看到这里 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.