C++ C++;

C++ C++;,c++,templates,specialization,differentiation,C++,Templates,Specialization,Differentiation,我想写一个函数,用于故障安全访问std::map 在我的代码中的许多地方,我希望通过键访问std::map,但如果键不存在,我希望有一种默认值,而不是异常(这是很多“无”代码) 我编写了这个基于模板的函数 template <typename T1, typename T2> T2 mapGetByKey(std::map<T1, T2>& map, T1 key, T2 defaultValue={}) { auto it = map.find(key)

我想写一个函数,用于故障安全访问
std::map

在我的代码中的许多地方,我希望通过键访问
std::map
,但如果键不存在,我希望有一种默认值,而不是异常(这是很多“无”代码)

我编写了这个基于模板的函数

template <typename T1, typename T2>
T2 mapGetByKey(std::map<T1, T2>& map, T1 key, T2 defaultValue={})
{
    auto it = map.find(key);

    if (it != map.end())
    {
        return it->second;
    }

    return defaultValue;
};
模板
T2-mapGetByKey(std::map&map,T1键,T2-defaultValue={})
{
auto it=map.find(键);
if(it!=map.end())
{
返回->秒;
}
返回默认值;
};
它工作得很好。但是对于
std::map
我希望有一个不同的行为。因此,我可以添加此专门化:

template <typename T1>
const char* mapGetByKey(std::map<T1, const char*>& map, T1 key, const char* defaultValue="")
{
    auto it = map.find(key);

    if (it != map.end())
    {
        return it->second;
    }

    return defaultValue;
};
模板
const char*mapGetByKey(std::map&map,T1键,const char*defaultValue=”“)
{
auto it=map.find(键);
if(it!=map.end())
{
返回->秒;
}
返回默认值;
};
它也起作用。但我认为这只是一个案例的大量代码

有人知道如何在不将默认值设置为
的情况下为
std::map
上的调用保存行吗

有没有一种方法可以在编译时区分类型,可以使用一些
ifdef
或类似的东西?

选项#1
模板
T defaultValue()
{
返回{};
}
模板
常量字符*默认值()
{
返回“默认字符串”;
}
模板
T2 mapGetByKey(标准::映射和映射,常量T1和键)
{
auto it=map.find(键);
if(it!=map.end())
{
返回->秒;
}
返回defaultValue();
}

选项2
模板结构标识{using type=T;};
模板
T2 mapGetByKey(std::map&map,T1键,常量typename标识::type&defaultValue={})
{
auto it=map.find(键);
if(it!=map.end())
{
返回->秒;
}
返回默认值;
}
模板
常量字符*mapGetByKey(标准::映射和映射,常量T1和键)
{
返回mapGetByKey(映射,键,“默认字符串”);
}

您可以为默认值添加模板函数,并为特定类型添加其专用版本:

template <typename T>
T default_value() { return {}; }
template <>
const char* default_value<const char*>() { return ""; }
模板
T default_value(){return{};}
模板
常量字符*默认值(){return”“;}
然后

template <typename T1, typename T2>
T2 mapGetByKey(std::map<T1, T2>& map, T1 key, T2 defaultValue=default_value<T2>())
模板
T2 mapGetByKey(标准::映射和映射,T1键,T2默认值=默认值()

非常感谢您!我没有看到这种简单但非常有效的可能性

结合这两种方法,同时添加基于情境的不同defaultValue的功能,我最终做到了:

template <typename T>
constexpr T mapGetByKeyDefaultValue()
{
    return {};
};

template <>
constexpr const char* mapGetByKeyDefaultValue<const char*>()
{
    return "";
};

template <typename T1, typename T2>
T2 mapGetByKey(std::map<T1, T2>& map, T1 key, T2 defaultValue=mapGetByKeyDefaultValue<T2>())
{
    auto it = map.find(key);

    if (it != map.end())
    {
        return it->second;
    };

    return defaultValue;
};
模板
constexpr T mapGetByKeyDefaultValue()
{
返回{};
};
模板
constexpr const char*mapGetByKeyDefaultValue()
{
返回“”;
};
模板
T2 mapGetByKey(std::map&map,T1键,T2 defaultValue=mapGetByKeyDefaultValue())
{
auto it=map.find(键);
if(it!=map.end())
{
返回->秒;
};
返回默认值;
};

将实现放在第三个函数中(没有默认值),并从现有模板调用该函数。是否考虑设置一个抽象的映射值结构来包装结果?然后,您可以在默认值和结果值之间进行区分。版本2听起来不错,但当尝试为defaultValue添加第三个参数时,它将进入一个无限循环(因为它调用自己而不是常规版本)。@SchubiDuah如果添加默认值,重载解析将选择第一个版本,您甚至不希望调用第二个参数,因为map并不总是有两个模板参数,它可以有更多的模板参数,当它有时,您的两个示例都会失败。
constexpr
不是必需的。@Jarod42我认为默认值应该是编译时的问题,我错在哪里了?默认值可能是(结果)一个常规函数(每次都被调用)。@Jarod42所以这肯定是运行时的问题……谢谢。
template <typename T1, typename T2>
T2 mapGetByKey(std::map<T1, T2>& map, T1 key, T2 defaultValue=default_value<T2>())
template <typename T>
constexpr T mapGetByKeyDefaultValue()
{
    return {};
};

template <>
constexpr const char* mapGetByKeyDefaultValue<const char*>()
{
    return "";
};

template <typename T1, typename T2>
T2 mapGetByKey(std::map<T1, T2>& map, T1 key, T2 defaultValue=mapGetByKeyDefaultValue<T2>())
{
    auto it = map.find(key);

    if (it != map.end())
    {
        return it->second;
    };

    return defaultValue;
};