簡體   English   中英

為什么const_cast不能處理std :: function的參數?

[英]Why doesn't const_cast work on arguments to std::function?

我正在提供成員函數的const和非const變體,其中我重用const版本來實現非const版本, 如本答案中描述的每個Scott Meyers書籍。

const版本采用類型的參數:

const std::function< void (const Foo &) > &

vs非const采用類型的參數:

const std::function< void (      Foo &) > &

在實現中,我必須使用reinterpret_cast因為const_cast不起作用。

例如,:

const std::function< void (Foo &) > & Processor;
reinterpret_cast< const std::function< void (const Foo &) > & >( Processor );

VS

const std::function< void (Foo &) > & Processor;
const_cast< const std::function< void (const Foo &) > & >( Processor );

這不符合const_cast的意思嗎? 這只是對語言定義的疏忽,或許可以在C ++ 2x中修復,或者const_cast永遠不會符合這里的精神?

這是更完整的代碼:

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 );
}

一般來說,使用const_cast來拋棄模板參數中出現的const是不安全的。 例如,考慮這個(誠然,有些人為的)代碼:

template <typename T> struct Wrapper {
    int x;
};

template <> struct Wrapper<char *> {
    double y;
};

在這里,一個指向Wrapper<const char *>指向一個非常不同的對象比Wrapper<char *>所以做了const_cast把一個Wrapper<const char *> *Wrapper<char *> *將導致在一個指向struct的指針中,該struct包含一個int現在指向一個包含doublestruct ,打破了一些語言規則,其名稱目前不在我身上。 :-)

因為一般來說const_cast這種方式不安全,語言規范不允許像這樣使用const_cast ,這就是為什么在你的情況下,即使操作直觀,語言也不允許使用const_cast代碼。

我相當肯定在這里使用reinterpret_cast會導致未定義的行為,因為語言認為std::function<T1>std::function<T2>是不同的,當T1T2不相同時,不兼容的類型。 它可能恰巧在您的系統上運行純粹巧合,但我不相信您可以安全地認為這將起作用。

reinterpret_cast這里是未定義的行為。 const_cast不合適,因為模板參數的const不是你可以拋棄的東西。

解決這個問題的簡單方法是,不要這樣做。 擺脫一些參考。 交換誰實現它。

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存儲與它調用兼容的東西。

如果你選擇Foo& ,你可以調用一個期望Foo const&它的Foo const& 所以你可以在std::function<void(Foo const&)>存儲一個std::function<void(Foo const&)> std::function<void(Foo&)>

std::function包裝內容可能涉及分配。 因此,您可能希望找到一個高質量的function_view<Sig>來替換您對std::function

在另一條評論中,您聲明此代碼處於關鍵循環中。 完全消除std::function是一個很好的舉動,或者至少減少類型擦除點擊並以某種方式將批量數據傳遞給它。

const / unest的反轉仍然是合適的; 我們用const表示const而不是const的變量,因為一個是協變運算,另一個是逆變運算。 看到這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM