注: 「msg(int32_t)」および「msg(int64_t)」の候補を使用した「msg(long)」のような関数のあいまいなオーバーロードで、同様の、しかし大幅に簡略化されたバージョンの問題を追加しました。このバージョンには、1 つのファイルに完全にコンパイル可能な例があるという利点があります。
問題
次のような関数を備えたCライブラリがあります
obj_from_int32(int32_t& i);
obj_from_int64(int64_t& i);
obj_from_uint32(uint32_t& i);
obj_from_uint64(uint64_t& i);
この場合、型int32_t
などは型ではありませんstd
- これらは実装定義であり、この場合は char の配列です (次の例では変換を省略しています - 整数型を型にマッピングすることに関する質問は変わりません)整数型のビット数に基づく特定の関数)。
次のようなコンストラクタを持つ2番目のC++インターフェイスクラスがあります
MyClass(int z);
MyClass(long z);
MyClass(long long z);
MyClass(unsigned int z);
MyClass(unsigned long z);
MyClass(unsigned long long z);
このインターフェイスをstd::int32_t
スタイル タイプに置き換えることはできないことに注意してください。できれば、この質問をする必要はありません ;)
obj_from_
問題は、整数型のビット数に基づいて正しい関数を呼び出す方法です。
提案されたソリューション
リストの一番上に浮かんでいるキラーソリューションはなく、壊れているものもいくつかあるため、2つの提案されたソリューションを掲載しています。
解決策 1
Cheers および hth提供。- アルフ。この時点からのコメントは私自身のものです。自由にコメントおよび/または編集してください。
利点
- かなりシンプル (少なくとも に比べてboost::enable_if
) - サードパーティのライブラリに依存しない (コンパイラがサポートしている限りtr1
)
*短所** - より多くの関数 (anotherObj_from_int32
など) が必要な場合は、さらに多くのコードが必要になります。
この解決策は以下にあります - 見てください。
解決策 2
利点
関数が完成したら、
ConvertFromIntegral
変換が必要な新しい関数を追加するのは簡単です - オーバーロードされたセットと符号なしの等価物を書くだけint32_t
ですint64_t
。テンプレートの使用は 1 か所のみにとどめます。テクニックが再利用されるため、テンプレートは広がりません。
短所
- を使用すると、非常に複雑になる可能性があります
boost::enable_if
。これが 1 か所にしか表示されないという事実によって、いくらか軽減されます。
これは私自身のものなので、私はそれを受け入れることはできませんが、それがきちんとしていると思うなら、賛成票を投じることができます(明らかに、まったくきちんとしているとは思わない人もいます。それが反対票を投じるものだと思います!)アイデアを投稿しました!
int
解決策には、からlong
およびlong long
へint32_t
の変換関数が含まれますint64_t
(署名なしバージョンについても同様です)。int32_t
これは、でオーバーロードされた別の関数セットint64_t
および符号なしの等価物と組み合わされます。2 つの関数を組み合わせることができますが、最初の変換関数は再利用できる便利なユーティリティ セットを作成し、2 番目の関数セットは自明のことです。
// Utility conversion functions (reuse wherever needed)
template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(int32_t) && boost::is_signed<InputT>::value,
int32_t>::type ConvertFromIntegral(InputT z) { return static_cast<int32_t>(z); }
template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(int64_t) && boost::is_signed<InputT>::value,
int64_t>::type ConvertFromIntegral(InputT z) { return static_cast<int64_t>(z); }
template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(uint32_t) && boost::is_unsigned<InputT>::value,
uint32_t>::type ConvertFromIntegral(InputT z) { return static_cast<uint32_t>(z); }
template <class InputT>
typename boost::enable_if_c<sizeof(InputT)==sizeof(uint64_t) && boost::is_unsigned<InputT>::value,
uint64_t>::type ConvertFromIntegral(InputT z) { return static_cast<uint64_t>(z); }
// Overload set (mock implementation, depends on required return type etc)
void* objFromInt32 (int32_t i) { obj_from_int32(i); }
void* objFromInt64 (int64_t& i) { obj_from_int64(i); }
void* objFromUInt32(uint32_t& i) { obj_from_uint32(i); }
void* objFromUInt64(uint64_t& i) { obj_from_uint64(i); }
// Interface Implementation
MyClass(int z) : _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(long z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(long long z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(unsigned int z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(unsigned long z): _val(objFromInt(ConvertFromIntegral(z))) {}
MyClass(unsigned long long z): _val(objFromInt(ConvertFromIntegral(z))) {}
ソリューションの単純化された (単一のコンパイル可能.cpp
!) バージョンは、候補 `msg(int32_t)` および `msg(int64_t)` を持つ `msg(long)` のような関数のあいまいなオーバーロードで提供されます。