2017-11-13 15 views
0

constexprstd::arrayを使用して、単純なコンパイル時のBimapを作成しようとしています。コンパイル時間Bimap static_assertのエラー

これは、最初の例でうまくいくようです。ここで

error: static_assert failed "3 == 3.3"
static_assert(meta_dict.find_key_of_value(3) == 3.3, "3 == 3.3"); // fails

Wandboxで利用可能なコード: は、しかし、第二の例で私は、次の静的エラーを持っています。上記のエラーを除いて、Clang>=5.0.0GCC>=8.0.0でコンパイルする必要があります。

#include <utility> 
#include <array> 
#include <stdexcept> 
#include <string_view> 
#include <iostream> 

template<class Key, class Value, std::size_t N> 
struct MetaBimap { 
    using Item = std::pair<Key, Value>; 

    constexpr MetaBimap(const std::array<Item, N>& d) 
     : dictionnary{d} 
     {} 

    constexpr Value find_value_of_key(const Key& key, int range = N) const 
    { 
     if (range == 0) 
      throw std::out_of_range("Cannot find key"); 
     return (dictionnary[range - 1].first == key) 
      ? dictionnary[range - 1].second 
      : find_value_of_key(key, range - 1); 
    } 

    constexpr Key find_key_of_value(const Value& value, int range = N) const 
    { 
     if (range == 0) 
      throw std::out_of_range("Cannot find value"); 
     return (dictionnary[range - 1].second == value) 
      ? dictionnary[range - 1].first 
      : find_key_of_value(value, range - 1); 
    } 

    std::array<Item, N> dictionnary; 
}; 


int main() 
{ 
    // first example 
    { 
     using namespace std::string_view_literals; 
     constexpr std::array<std::pair<std::string_view, int>, 3> meta_array {{ 
      { "one"sv, 1 }, 
      { "two"sv, 2 }, 
      { "three"sv, 3 } 
     }}; 
     constexpr MetaBimap<std::string_view, int, 3> meta_dict = meta_array; 

     // OK on wandbox with Clang>=5.0.0 and GCC>=8.0.0 (though not working on my computer with Clang=5.0.0) 
     static_assert(meta_dict.find_value_of_key("one"sv) == 1, "one == 1");  
     static_assert(meta_dict.find_key_of_value(3) == "three"sv, "3 == three"); 
    } 

    // second example 
    { 
     constexpr std::array<std::pair<float, int>, 3> meta_array {{ 
      { 1.1, 1 }, 
      { 2.2, 2 }, 
      { 3.3, 3 } 
     }}; 
     constexpr MetaBimap<float, int, 3> meta_dict = meta_array; 

     static_assert(meta_dict.find_value_of_key(1.1) == 1, "1.1 == 1");  // OK 
     std::cout << meta_dict.find_key_of_value(3) << std::endl; 
     // static_assert(meta_dict.find_key_of_value(3) == 3.3, "3 == 3.3"); // fails 
    } 
} 

なぜここで静的なエラーが発生し、それを修正するのですか? また、ボーナスとして、バイマップの構築を簡素化する方法はありますか?

答えて

4

問題はこれまで低減することができる。

constexpr float a = 3.3; 
static_assert (a == 3.3f, "float 3.3 is different from literal compiled 3.3f"); // ok 
static_assert (a == 3.3, "float 3.3 is different from literal compiled 3.3"); //this fails 

コードで記述されたリテラル3.3ダブルとしてコンパイラによって処理され、そしてそれらを異なる精度を有する二重有するフロートを比較した場合、それが起こることができます(ほとんど常に)、彼らはあなたが任意のサフィックスを指定していない間double

にデフォルト設定されます、コードで記述されたリテラルは floatとして扱われるべきであるコンパイラを言っている 3.3f

と一致しません

見てくださいhere

+0

これは、浮動小数点数を使用するとキーが最も危険であることを示しています。 – Walter

+0

必ず@Walter! –

+0

@GianPaoloねえ、私は愚かだと感じる...ありがとう。 – coincoin

関連する問題