std :: map的std :: size_type,其value_type是其自身的size_type

时间:2018-11-22 12:41:31

标签: c++ c++11 stl stdmap size-type

我有一个std::map<std::pair<std::string, std::string>, float>占用了过多的内存,为了使用更少的内存,我决定将唯一的字符串映射为整数(例如std::map<std::string, int>,其中每个新唯一字符串被映射到地图的当前size(),并使用这些整数值作为地图的成对键(例如std::map<std::pair<int, int>, float>)。

我要使用std::map::size_type而不是int

using map_index = std::map::size_type;
std::pair<map_index, map_index> key;

当然,这不会编译,因为我需要提供地图的参数列表:

vector.cc:14:19: error: invalid use of template-name `std::map' without an argument list
 using map_index = std::map::size_type;

(理论上)这就是我要实现的目标:

using map_index = std::map<std::string, map_index>::size_type;

会出现以下(预期的)编译器错误:

vector.cc:15:41: error: `map_index' was not declared in this scope
 using map_index = std::map<std::string, map_index>::size_type;

让编译器为value_type是自己的std::map的{​​{1}}推断正确的value_type的正确方法是什么?

7 个答案:

答案 0 :(得分:5)

sudo pip list | grep docker应该足以应付这种情况。

但是,如果您坚持要这样做,可以这样做:

size_t

它将在#include <type_traits> #include <map> template <class Key, class Value = size_t, size_t depth = 0, class = void> struct GetSizeType { using type = typename GetSizeType<Key, typename std::map<Key, Value>::size_type, depth + 1>::type; }; template <class Key, class Value, size_t depth> struct GetSizeType<Key, Value, depth, std::enable_if_t<std::is_same_v<Value, typename std::map<Key, Value>::size_type>>> { using type = typename std::map<Key, Value>::size_type; }; template <class Key, class Value> struct GetSizeType<Key, Value, 100, void> {}; int main() { using X = GetSizeType<int>::type; return 0; } 上递归运行,递归调用将在此终止

  • 达到递归调用深度限制(在这种情况下,将没有成员GetSizeType),或者
  • 找到typestd::map相同(成员mapped_type别名size_type)相同的type的专业化。

答案 1 :(得分:4)

免责声明:此解决方案非常笨。我们将通过反复(通常一次)尝试实例化std::map来求解方程式,直到找到一个具有请求的键并将其自己的size_type作为值的值。

template <class T>
struct identity {
    using type = T;
};

template <class K, class V = char>
struct auto_map {
    using map_type = std::map<K, V>;
    using type = typename std::conditional_t<
        std::is_same_v<
            typename map_type::mapped_type,
            typename map_type::size_type
        >,
        identity<map_type>,
        auto_map<K, typename map_type::size_type>
    >::type;
};

template <class K>
using auto_map_t = typename auto_map<K>::type;

如果元函数找不到这样的映射,则它会因为type最终被定义为错误而出错,或者会破坏递归限制。

答案 2 :(得分:2)

使用std::size_t。无符号整数std::map::size_type不会大于std::size_t,并且实际上是相同的类型。

如果您想确定的话,请断言:

static_assert(std::is_same_v<
    std::size_t,
    std::map<std::string, std::size_t>::size_type
>);

答案 3 :(得分:2)

我在野外使用的所有C ++实现都对所有地图使用相同的大小类型。

所以;

using map_size_type = std::map<int, int>::size_type;
using my_map = std::map<std::string, map_size_type>;
static_assert(std::is_same<map_size_type, my_map::size_type);

如果(合理的)假设失败,这只会导致编译错误。

答案 4 :(得分:1)

但是您确定size_type中的std::map取决于键/值类型吗?

如果是这样,我看不到获得它的方法。

但是size_type不应取决于键/值类型,通常应为std::size_t

我建议

using Index0 = typename std::map<std::string, std::size_t>::size_type;

using mapIndex = typename std::map<std::string, Index0>::size_type;    

您可以通过以下方式检查您输入的类型是否正确

static_assert( std::is_same_v<Index0, mapIndex>, "no right type");

答案 5 :(得分:1)

打破循环依赖的唯一方法是使用特定类型。我建议您简单地使map_index成为std::size_t-C ++强烈Working Examplestd::size_t分配给map::size_type

答案 6 :(得分:1)

通常来说,您要寻找的是不可能的。

可以想象(虽然牵强)std::map<int, long>::size_typeint,而std::map<int, int>::size_typelong(对于其他整数类型也是如此),在这种情况下不存在满足std::map<int, T>::size_typeT的可能方式。

相反,对于所有std::map<int, T>::size_typeT被定义为T,在这种情况下,没有唯一的T可以满足您的“要求”。

如几个答案(和您自己的参考链接)所述,实际上,除了size_t之外,不可能没有其他内容。