You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++11中使用万能引用合并两个map_at函数?

用C++11万能引用合并两个map_at函数的解决方案

问题背景

需要将处理const和非const容器的两个map_at函数,通过C++11的万能引用T&&合并为单一模板函数。原代码如下:

#include <map>
#include <exception>

template<typename T> // const版本
const typename T::mapped_type& map_at(const T& m, const typename T::key_type& key)
{
    if (const auto& iter = m.find(key); iter != m.cend()) {
        return iter->second;
    }
    else {
        throw std::exception("blah");
    }
}

template<typename T> // 非const版本
typename T::mapped_type& map_at(T& m, const typename T::key_type& key)
{
    if (const auto& iter = m.find(key); iter != m.cend()) {
        return iter->second;
    }
    else {
        throw std::exception("blah");
    }
}

int main()
{
    using T = std::map<int, float>;
    T t;
    const T ct;

    try {
        map_at(ct, 3); // 调用const版本
    }
    catch (...){}

    try {
        map_at(t, 3); // 调用非const版本
    }
    catch (...){}
}

尝试使用万能引用的版本出现编译错误:

1> ConsoleApplication1.cpp(557,9): error C2672: 'map_at': no matching overloaded function found

错误版本代码:

template<typename T> // T&&版本
typename T::mapped_type&& map_at(T&& m, const typename T::key_type& key)
{
    if (const auto& iter = m.find(key); iter != m.cend()) {
        return iter->second;
    }
    else {
        throw std::exception("blah");
    }
}

错误原因分析

  1. 返回值类型错误:当传入const左值容器时,T会被推导为const std::map<int, float>&,此时typename T::mapped_type&&是右值引用,但容器中元素的类型是const float&,无法绑定到右值引用,导致类型不匹配。
  2. key类型推导错误:当T是引用类型时,T::key_type会编译失败——引用类型没有嵌套的key_type,必须先移除引用,获取原始容器类型的嵌套类型。

正确实现(C++11兼容)

利用C++11的类型萃取工具std::remove_reference和std::conditional,推导正确的返回值类型,并修正key的参数类型:

#include <map>
#include <stdexcept>
#include <type_traits>

template<typename T>
auto map_at(T&& m, const typename std::remove_reference<T>::type::key_type& key)
-> typename std::conditional<
    std::is_const<typename std::remove_reference<T>::type>::value,
    const typename std::remove_reference<T>::type::mapped_type&,
    typename std::remove_reference<T>::type::mapped_type&
>::type
{
    auto iter = m.find(key);
    if (iter != m.cend()) {
        return iter->second;
    }
    throw std::runtime_error("Key not found in map");
}

int main()
{
    using Map = std::map<int, float>;
    Map mutable_map;
    const Map const_map;

    try {
        // 获取const引用,对应原const版本
        const float& val1 = map_at(const_map, 3);
    }
    catch (const std::exception&) {}

    try {
        // 获取非const引用,对应原非const版本
        float& val2 = map_at(mutable_map, 3);
    }
    catch (const std::exception&) {}
}

代码说明

  • std::remove_reference<T>::type:移除T的引用属性,获取原始容器类型(比如const std::map<int, float>或std::map<int, float>)。
  • std::conditional:根据原始容器是否为const类型,选择返回const mapped_type&或mapped_type&,完美匹配原两个版本的返回值语义。
  • 参数key的类型改为const typename std::remove_reference<T>::type::key_type&,确保无论T是引用还是值类型,都能正确获取容器的key类型。

内容的提问来源于stack exchange,提问作者user9636586

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 08:36:12