5

失われたデータを適切に無視するナローイング キャスト (一般的な解決策) を考え出そうとしています。Visual Studio では、データを失うナローイング キャストによって "Run-Time Check Failure #1" がトリガーされます。私はそれをオフにしたくありません。代わりに、narrow_cast狭いキャストを適切に実行し、実行時チェックをトリガーしない a を実装しようとしています。

Visual Studio は次のことを提案します。

char c = (i & 0xFF);

だから私はこれから始めて、この醜い解決策を思いついた:

template< typename T >
struct narrow_mask
{
  static const T value = T(0xFFFFFFFFFFFFFFFF);
};

template <typename T, typename U>
T narrow_cast(const U& a)
{
  return static_cast<T>(a & narrow_mask<T>::value );
}

それは機能しますが(VSは定数のデータを失うことで完全に問題ないようです)、完全ではなく(非整数データをサポートしていません)、正しくもありません(符号付きの値では正しく機能しないと思います)。

より良い解決策、またはより良いnarrow_maskの実装に関する提案はありますか?

編集:この質問は VS 固有であるというコメントに直面して、標準ドキュメントを確認しましたが、絞り込みの結果static_castは実装に依存するようです。したがって、この質問は、明確に定義された (したがって、実装に依存しない) ナローイング キャストを作成するものとしてより適切に述べることができます。結果値が明確に定義されていて、タイプ ( ではない) に依存している限り、結果値の詳細についてはあまり気にしませんreturn 0

4

4 に答える 4

6

これは、C++11 を少し使用したバージョンの 1 つです。にアクセスできない場合はconstexpr、削除するだけです。にアクセスできない場合はstd::make_unsigned、独自のものを実装できます。持っていない場合はstd::enable_if、Boost を使用する (または独自に作成する) ことができる場合があります。これは、正と負の値だけでなく、符号付きと符号なしの両方の型でも機能します。更新: 浮動小数点型 (および浮動小数点から整数、およびその逆) で動作するように更新されました。

#include <type_traits>

// From integer type to integer type
template <typename to, typename from>
constexpr typename std::enable_if<std::is_integral<from>::value && std::is_integral<to>::value, to>::type
narrow_cast(const from& value)
{
    return static_cast<to>(value & (static_cast<typename std::make_unsigned<from>::type>(-1)));
}

// For these next 3 versions, you'd be best off locally disabling the compiler warning
// There isn't much magic you can do when floating point types get invovled

// From floating point type to floating point type
template <typename to, typename from>
constexpr typename std::enable_if<std::is_floating_point<from>::value && std::is_floating_point<to>::value, to>::type
narrow_cast(const from& value)
{
    // The best you can do here is a direct cast
    return static_cast<to>(value);
}

// From integer type to floating point type
template <typename to, typename from>
constexpr typename std::enable_if<std::is_integral<from>::value && std::is_floating_point<to>::value, to>::type
narrow_cast(const from& value)
{
    // The best you can do here is a direct cast
    return static_cast<to>(value);
}

// From floating point type to integer type
template <typename to, typename from>
constexpr typename std::enable_if<std::is_floating_point<from>::value && std::is_integral<to>::value, to>::type
narrow_cast(const from& value)
{
    // The best you can do here is a direct cast
    return static_cast<to>(value);
}
于 2013-07-27T16:28:36.787 に答える