

実行時にネイティブエンディアンがリトルエンディアンか否かは、例えば以下のように判定できます。

[code]

    #include <iostream>
    
    const int bom = 1;
    bool is_little_endian() {
        return *reinterpret_cast<const char *>(&bom) == 1;
    }
    
    int main()
    {
        const bool b = is_little_endian();
        std::cout << b << '\n';
    }
    
[/code]

C++11で定数式の機能(constexpr)が追加されたので、constをconstexprに変えればコンパイル時に判定できるのではないかと考えたのですが、reinterpret_castは定数式の中では使えないようで、コンパイルエラーになります。

[code]

    #include <iostream>
    
    constexpr int bom = 1;
    constexpr bool is_little_endian() {
        return *reinterpret_cast<const char *>(&bom) == 1;
    }
    
    int main()
    {
        constexpr bool b = is_little_endian();
        std::cout << b << '\n';
    }
    
[/code]

;

[code]

    # clang++ -Wall -std=c++11 test_endian.cpp
    test_endian.cpp:4:16: error: constexpr function never produces a constant
          expression [-Winvalid-constexpr]
    constexpr bool is_little_endian() {
                   ^
    test_endian.cpp:5:10: note: reinterpret_cast is not allowed in a constant
          expression
            return *reinterpret_cast<const char *>(&bom) == 1;
                    ^
    1 error generated.
    
[/code]

コンパイル時にはネイティブエンディアンは決まっていると思うのでコンパイル時に判定したいのですが、Boostライブラリのようにコンパイラー独自のマクロで判定する方法以外で、何か方法はありますか？

※リトルエンディアンか否かだけではなく、リトルエンディアン／ビッグエンディアン／その他に分類できればベストです。

* * *

■追記  
用途としては、外部データと内部データを変換する関数／クラスを作る場合に、外部データのエンディアンとネイティブエンディアンの関係で実装を最適化する、ということを想定しています。


CC BY-SA 3.0
2015-06-18T04:35:31.610
11458
2017-07-25T04:21:49.897
2015-06-18T14:44:23.583
7291
7291
question
c++ c++11
コンパイル時にネイティブエンディアンを判定するには？


標準のものかどうかはなはだ疑問ではありますが、CentOS では /usr/include/ 下とか MacOS では
/usr/include/machine/ 下とかに endian.h といふのがあるやうです。

[code]

    #include <machine/endian.h>
    
    #if __BYTE_ORDER == __LITTLE_ENDIAN
    ...
    #elif __BYTE_ORDER == __BIG_ENDIAN
    ...
    #endif
    
[/code]


CC BY-SA 3.0
2015-06-18T05:39:06.880
11462
2015-06-18T05:39:06.880
4381
11458
answer


[yoh2さんコメント](https://ja.stackoverflow.com/questions/11458/#comment10371_11458)にある通り、C++14時点のconstexpr関数ではコンパイル時エンディアン判定は不可能です。本家SOの類似質問でも全てNO回答です。

  * [Is there a way to do a C++ style compile-time assertion to determine machine's endianness?](https://stackoverflow.com/questions/280162/)
  * [constexpr and endianness](https://stackoverflow.com/questions/1583791/)

Boost Libraryを使用できる環境ならば、下記が便利かと思います。いずれもC++03から使えるヘッダオンリーライブラリです。

  * Boost Predefの[`BOOST_ENDIAN_*`マクロ](http://www.boost.org/doc/libs/1_58_0/libs/predef/doc/html/predef/reference/other_macros.html)
  * [Boost Endian Library](http://www.boost.org/doc/libs/1_58_0/libs/endian/doc/)（Boost 1.58.0以降）

* * *

**追記：** まだC++17正式発行前で気の早い話ですが、将来のC++標準ライブラリ(C++20)には
[`std::endian`](http://en.cppreference.com/w/cpp/types/endian)
が追加され、コンパイル時のネイティブエンディアン判定が可能になります。

[code]

    // require C++20
    # include <type_traits>
    constexpr bool is_little_endian() {
        return std::endian::native == std::endian::little;
    }
    
[/code]

(via
<https://www.reddit.com/r/cpp/comments/6ngkgc/2017_toronto_iso_c_committee_discussion_thread/>)


CC BY-SA 3.0
2015-06-21T00:37:56.140
11567
2017-07-25T04:21:49.897
2017-07-25T04:21:49.897
49
49
11458
answer