C++ 模板 type_trait enable_if 类是映射

标签 c++ templates type-traits decltype enable-if

#include <iostream>
#include <any>
#include <vector>
#include <map>
#include <unordered_map>
#include <string>
using namespace std;

// enable_if_t = MapType implements .find(KeyType key), .begin(), .end(), and .begin() 
// and MapType::iterator it has it->first and it->second
template<typename MapType>
decltype(declval<MapType>().begin()->second) MapGetOrDefault(
    MapType mymap, 
    decltype(declval<MapType>().begin()->first) key, 
    decltype(declval<MapType>().begin()->second) defaultValue = decltype(declval<MapType>().begin()->second){}
    )
{
    auto it = mymap.find(key);
    if (it!=mymap.end()) return it->second;
    else return defaultValue;
}

int main()
{   
    map<string, int> a;
    unordered_map<int, string> b;
    
    a["1"] = 2;
    cout << MapGetOrDefault(a, "1") << " " << MapGetOrDefault(a, "2") << " " << MapGetOrDefault(a, "2", -1) << "\n";

    b[1] = "hello";
    cout << MapGetOrDefault(b, 1) << " " << MapGetOrDefault(b, 2) << " " << MapGetOrDefault(b, 3, "world") << "\n";

    return 0;
}

我正在尝试制作一个通用的 get_or_default()可以与所有类型的 map 一起使用的功能。类必须满足 4 个条件才能算作映射,如代码注释所示。

如何使用 C++ 类型特征来做到这一点?另外,如何更改decltype(declval<MapType>().begin()->first)变成更干净的东西?

编辑:是enable_if_t在这种情况下甚至需要?我的目标只是防止编译

最佳答案

map 具有可以使用的成员别名mapped_typekey_type(和value_type):

#include <iostream>
#include <any>
#include <vector>
#include <map>
#include <unordered_map>
#include <string>
using namespace std;

template<typename MapType>
typename MapType::mapped_type MapGetOrDefault(
    MapType mymap, 
    typename MapType::key_type key, 
    typename MapType::mapped_type defaultValue = typename MapType::mapped_type{}
    )
{
    auto it = mymap.find(key);
    if (it!=mymap.end()) return it->second;
    else return defaultValue;
}

int main()
{   
    map<string, int> a;
    unordered_map<int, string> b;
    
    a["1"] = 2;
    cout << MapGetOrDefault(a, "1") << " " << MapGetOrDefault(a, "2") << " " << MapGetOrDefault(a, "2", -1) << "\n";

    b[1] = "hello";
    cout << MapGetOrDefault(b, 1) << " " << MapGetOrDefault(b, 2) << " " << MapGetOrDefault(b, 3, "world") << "\n";

    return 0;
}

模板别名可以帮助实现更简洁的语法:

template <typename T> using mapped_type = typename T::mapped_type;

template <typename T> using key_type = typename T::key_type;

template<typename MapType>
mapped_type<MapType> MapGetOrDefault(
    MapType mymap, 
    key_type<MapType> key, 
    mapped_type<MapType> defaultValue = mapped_type<MapType>{}
    )
{
    auto it = mymap.find(key);
    if (it!=mymap.end()) return it->second;
    else return defaultValue;
}

PS:我没有更改它,因为它不是问题的一部分,但是在将 map 传递给函数时不应该复制 map ,而是使用 const MapType& mymap 作为论证。

PPS:正如 Caleth 在评论中提到的,使用透明比较器,即具有 Comparator::is_transparent 成员类型的比较器,您可能希望支持此处列出的重载 (4): https://en.cppreference.com/w/cpp/container/map/find通过引入另一个可以从 key 参数推导出来的模板参数 KeyType

关于C++ 模板 type_trait enable_if 类是映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71604607/

相关文章:

java - 将 C++ 对象实例存储在 JNI jobject 中并稍后检索

c++ - 基于类型的标签调度 : Is it possible to differently tag containers based on the tags of their elements?

python - Distutils:构建共享一个方法的多个Python扩展模块(用Swig编写)

C++标准对与 vector 加速

c++ - C++ 模板机制只是一个类型构建器函数吗?

django - 将附加参数传递给 django 登录名和模板

c++ - 传递给模板函数的两个 lambda 使参数的类型推导不明确——为什么?

c++ - 在类模板方法中使用enable_if来检查两个函数参数是否都是std::array或都是std::vector

c++ - 为什么这个 SFINAE 没有按预期工作?

C++、模板、静态函数