2017-02-02 10 views
2

次のコードは、CentOSシステム上でGCC 4.8.5とClang 3.9.1でコンパイルしますが、何もコンパイルしません(GCC、Clang)私のMacOSシステムで。どちらも64ビットシステムです。私はそれがそれらのシステムで使用される異なる標準ライブラリから来ていると思います。64ビットシステムで関数のオーバーロード、整数型とstd :: size_t

#include <iostream> 
#include <cstdint> 

std::int32_t f(std::int32_t a) { return 0; } 
std::uint32_t f(std::uint32_t a) { return 1; } 
std::int64_t f(std::int64_t a) { return 2; } 
std::uint64_t f(std::uint64_t a) { return 3; } 

int main() { 
    const std::size_t n = 0; 

    std::cout << f(n) << std::endl; 

    return 0; 
} 

MacOSでは、あいまいなオーバーロードについて不平を言います。私はstd::size_tstd::uint64_tが64ビットシステムで同じであると思ったので驚いています。私が遊んでいて

>> clang++ -std=c++11 main.cpp -o main 
main.cpp:12:16: error: call to 'f' is ambiguous 
std::cout << f(n) << std::endl; 
      ^
main.cpp:4:14: note: candidate function 
std::int32_t f(std::int32_t a) { return 0; } 
      ^
main.cpp:5:15: note: candidate function 
std::uint32_t f(std::uint32_t a) { return 1; } 
      ^
main.cpp:6:14: note: candidate function 
std::int64_t f(std::int64_t a) { return 2; } 
      ^
main.cpp:7:15: note: candidate function 
std::uint64_t f(std::uint64_t a) { return 3; } 
      ^
1 error generated. 

この例は愚かに見えるにもかかわらず、私は本当に私の実際のアプリケーションとその動作中/未署名の署名と32/64ビット整数のためf()をオーバーロードする必要があるが、整数のサイズに依存しなければなりませんビット付き。私は何をすべきか?

+0

:すべての可能な組み合わせでstd::enable_ifを使用しますか?あなたが知っているのは、それが* unsigned integer型*のtypedefであり、 'sizeof'、' sizeof ... 'または' alignof'演算子を使うときに得られるものです。 –

+0

@Toby 'std :: size_t'は符号なし整数(標準ではsoと書かれています)であり、両方のプラットフォームで64ビット(テスト済みなので)です。私はちょうど同じサイズと同じsignessの2つの整数型が異なる可能性があることに驚いています。私は今週、 'char'、' signed char'と 'unsigned char'は3つの異なる型ですが、この奇妙な振る舞いは' char'型だけで起こったと考えました。 – InsideLoop

+0

@Toby Cスタイルの関数 'f_unsigned'、' f_unsigned_long'を持っていることを知って、 'unsigned int'、' unsigned long'、 'unsigned long long'、' std :: size_t'の関数を定義したいのですが、 'f_unsigned_long_long'?どちらを定義して同じタイプの関数を2回定義しないかを決めなければなりません。それを行う方法さえありますか? – InsideLoop

答えて

1

単純な答え:std::size_tfを呼び出すことはありません - fで受け入れ、正確なタイプのいずれかでそれを呼び出します。


代替答え:あなたが唯一気におよそ符号の有無ビット数。あなたは `のstd :: size_t`が正確にそれらの整数のいずれかのタイプと一致しなければならないことだと思いますなぜ

template <typename T, bool Signed, int Size> 
using enable_if_sd = 
    typename std::enable_if< 
     std::is_signed<T>{} == Signed && sizeof(T) * CHAR_BIT == Size 
    >::type; 

template <typename T> 
void f(T, enable_if_sd<T, true, 32>* = nullptr) 
{ 
    std::cout << "signed 32-bit\n"; 
} 

template <typename T> 
void f(T, enable_if_sd<T, true, 64>* = nullptr) 
{ 
    std::cout << "signed 64-bit\n"; 
} 

template <typename T> 
void f(T, enable_if_sd<T, false, 32>* = nullptr) 
{ 
    std::cout << "unsigned 32-bit\n"; 
} 

template <typename T> 
void f(T, enable_if_sd<T, false, 64>* = nullptr) 
{ 
    std::cout << "unsigned 32-bit\n"; 
} 

coliru example

+0

それは複雑に見えます。もっとシンプルな方法があるとは思わない? – InsideLoop

+0

@InsideLoop:それについて考えてみましょう。それにもかかわらず、それはあなたの問題を解決しますか? –

+0

@InsideLoop:コードを簡略化しました。 –

関連する問題