2017-11-13 19 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 
    } 
} 

왜 여기에 정전기 오류가 발생하며이를 수정하는 이유는 무엇입니까? 또한 보너스로 bimap의 구성을 단순화하는 방법은 무엇입니까?

답변

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 이중으로 컴파일러에 의해 처리하고, 그들에게 다른 정밀도를 가진 이중으로 float를 비교할 때, 그것을 할 수있는 일이 (거의 항상) 그들이 어떤 접미사를 지정하지 않는 동안 double

로 설정됩니다 코드로 작성된 문자가 float로 처리해야 컴파일러를 말하고있다 3.3f

일치하지 않습니다

보기 here

+0

이것은 부동 소수점 숫자를 사용하면 키가 가장 위험하다는 것을 보여줍니다. – Walter

+0

확실히 @ 월터! –

+0

@GianPaolo 젠장, 어리 석다. .. 고마워. – coincoin