编译时 Bimap static_assert失败

Compile time Bimap static_assert failure

本文关键字:assert 失败 static Bimap 编译      更新时间:2023-10-16

我正在尝试使用constexprstd::array进行简单的编译时Bimap。

这似乎适用于第一个示例。但是,对于第二个示例,我有以下静态错误:

错误:static_assert失败"3 == 3.3">
static_assert(meta_dict.find_key_of_value(3( == 3.3, "3 == 3.3"(; 失败

这里是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的构建吗?

问题可以简化为:

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 被编译器视为双精度,当将浮点数与双精度进行比较时,它们具有不同的精度,可能会发生(几乎总是(它们不匹配的情况

使用 3.3f 您告诉编译器,用代码编写的文字应被视为float,而不指定任何后缀将默认为 double

看看这里