c++ - 编译时 Bimap static_assert 失败

标签 c++ c++17 compile-time

我正在尝试通过使用 constexprstd::array 获得一个简单的编译时 Bimap。

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

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 的构造?

最佳答案

问题可以简化为:

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 和 double 时,如果它们具有不同的精度,它们可能(几乎总是)不匹配

对于 3.3f,您是在告诉编译器在代码中编写的文字应被视为 float,而未指定任何后缀将默认为 double

看看here

关于c++ - 编译时 Bimap static_assert 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47262175/

相关文章:

c++ - 如何安全地实现 “Using Uninitialized Memory For Fun And Profit”?

java - 一个函数应该属于两个类中的一个/两个还是独立的?

c++ - const_forward 在 C++ 的可选实现中做了什么?

c++ - 有没有一种聪明的方法来实现完全静态的观察者模式(在编译时)

c++ - 在 C++11 中存储对方法的引用时出错

c++ - 在 map 中使用自定义删除器存储 unique_ptr

c++ - 使用强类型枚举的模板参数推导

c++ - Variadic 类模板和继承 - 默认编译器生成的构造函数

c++ - 我可以将编译时策略的创建和使用位置分开吗?

c++ - integral_constant 的编译时 bool 运算?