web-dev-qa-db-ja.com

「安全な」static_castの代替手段はありますか?

C++ 11/14のstatic_castの「安全な」代替手段、またはこの機能を実装するライブラリはありますか?

「安全」とは、キャストが精度を失わないキャストのみを許可することを意味します。したがって、int64_tからint32_tへのキャストは、番号がint32_tに収まる場合にのみ許可され、そうでない場合はエラーが報告されます。

16

_gsl::narrow_ があります

narrow // narrow<T>(x)は、static_cast<T>(x)の場合はstatic_cast<T>(x) == xであるか、_narrowing_error_をスローします

35
Caleth

ユースケースが逆になっています。

static_cast(および他のc ++スタイルのキャスト)の使用目的は、プログラマーの意図を示すことです。 auto value = static_cast<int32_t>(value_64);と書くと、「はい、この割り当てを実行するときに、この値をダウンキャストし、おそらく切り捨てるつもりです」。その結果、通常の状況(int32_t value = value_64;を書いた場合など)でこの変換について文句を言う傾向があるかもしれないコンパイラが、代わりにを観察します。これは彼らが意図したものです;なぜ彼らは私に嘘をつくのでしょうか?」そして静かにコードをコンパイルします。

C++コードが安全でない変換で警告またはエラーをスローするようにするには、明示的にnotstatic_castconst_castreinterpret_castを使用し、コンパイラーに許可する必要がありますその仕事をします。コンパイラには、警告の処理方法を変更するフラグがあります(通常、int64_tint32_tにダウンキャストすると、警告のみが発生します)。したがって、正しいフラグを使用して、警告を強制的にエラーとして処理してください。

21
Xirema

Sfinaeで独自に作成できます。以下に例を示します。

template <typename T, typename U>
typename std::enable_if<sizeof(T) >= sizeof(U),T>::type 
safe_static_cast(U&& val)
{
    return static_cast<T>(val);
}

int main()
{
    int32_t y = 2;
    std::cout << safe_static_cast<int32_t>(y) << std::endl;
    std::cout << safe_static_cast<int16_t>(y) << std::endl; // compile error
}

これは、キャストするサイズがソースサイズ以上の場合にのみコンパイルされます。

試してみてください こちら

他のタイプでは numeric_limits を使用し、 type_traits を使用すると、さらに複雑になります。

私の解決策はコンパイル時の解決策であることに注意してください。なぜならあなたがstatic_castについて尋ねたからです。