шаблоны — основанная на типе шаблонная функция в переполнении стека

Я хочу написать функцию, которая обеспечивает безопасный доступ 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;
};

Работает отлично. Но для std::map<int, const char*> Я хотел бы иметь другое поведение. Поэтому я мог бы добавить эту специализацию:

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;
};

Это тоже работает. Но я думаю, что это просто кусок кода только для одного случая.

Кто-нибудь есть идеи, как сохранить строки без настроек defaultValue "" для звонков на std::map<int, const char*>?

Есть ли способ различать типы во время компиляции, может быть, с некоторыми ifdef или что-то типа того?

7

Решение

Опция 1

template <typename T>
T defaultValue()
{
return {};
}

template <>
const char* defaultValue<const char*>()
{
return "default string";
}

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

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

return defaultValue<T2>();
}

ДЕМО 1

Вариант № 2

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

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

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

return defaultValue;
}

template <typename T1>
const char* mapGetByKey(std::map<T1, const char*>& map, const T1& key)
{
return mapGetByKey(map, key, "default string");
}

ДЕМО 2

4

Другие решения

Спасибо вам большое! Я не видел таких простых, но очень эффективных возможностей.

Комбинируя два метода при добавлении функциональности ситуации, основанной на различных 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;
};
1

Вы можете добавить функцию шаблона для значения по умолчанию и добавить ее специализированную версию для определенного типа:

template <typename T>
T default_value() { return {}; }
template <>
const char* default_value<const char*>() { return ""; }

А потом

template <typename T1, typename T2>
T2 mapGetByKey(std::map<T1, T2>& map, T1 key, T2 defaultValue=default_value<T2>())

ЖИТЬ

0
По вопросам рекламы [email protected]