繁体   English   中英

std :: map :: size_type用于std :: map,其value_type是它自己的size_type

[英]std::map::size_type for a std::map whose value_type is its own size_type

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

而不是int ,我想使用std :: map :: size_type

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;

让编译器为std::map推断正确value_type的正确方法是什么,其value_type是它自己的size_type

对于这种情况, 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上递归运行,递归调用将停止

  • 达到递归调用深度限制(在这种情况下将没有成员type ),或
  • 查找std::map的特化,其mapped_typesize_type相同(成员type别名为size_type )。

免责声明:这个解决方案非常愚蠢。 我们将通过重复(通常一次)尝试实例化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最终定义为自身,或者破坏递归限制。

使用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
>);

我使用的所有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);

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

但是你确定std::mapsize_type取决于键/值类型吗?

如果是这样,我没有办法得到它。

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");

打破循环依赖的唯一方法是使用特定类型。 我建议您只需将map_index设为std::size_t - C ++强烈暗示 std::size_t可以赋值给map::size_type

一般来说,你所寻找的是不可能的。

可以想象(尽管很牵强) std::map<int, long>::size_typeintstd::map<int, int>::size_typelong (对于其他整数类型也是如此),在这种情况下没有可能的方法来满足std::map<int, T>::size_typeT

相反,它可能是std::map<int, T>::size_type被定义为T所有T ,在这种情况下,没有独特的T满足您的“要求”。

正如几个答案(以及您自己的参考链接)所提到的,实际上它不可能是size_t以外的任何东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM