无论我传递的是字符串文字还是字符串对象,我如何才能让这个函数模板起作用?

how can I get this function template to work reguardless of whether I pass a string literal or a string object?

我有以下函数模板,它采用任何类型的映射和 returns 与特定键关联的值或调用站点提供的默认值:

template <template <typename Key, typename Val, typename ...Args> typename C, typename Key, typename Val, typename ...Args>
Val get_or_default(C<Key, Val, Args...> const& my_map, Key const& k, Val const& v)
{
    typename C<Key, Val, Args...>::const_iterator const it = my_map.find(k);
    return (it != my_map.end()) ? it->second : v;
}

当我这样调用函数时:

// initialize map
    std::map<std::string, int> m1{ {"jim",1},{"mark",2},{"sally",3} };
// call get_or_default with std::string as key arg
    std::cout << get_or_default(m1, std::string("jim"), -1) << std::endl;

一切都按预期工作,但是当我像这样调用函数时:

std::cout << get_or_default(m1, "jim", -1) << std::endl;

我收到以下错误消息:

error C2782: 'Val get_or_default(const C<Key,Val,Args...> &,const Key &,const Val &)': template parameter 'Key' is ambiguous

我认为参数 Key 不明确,因为它在地图模板中使用 std::string 调用,但作为 get_or_default 的第二个参数调用 const char*

无论我传递的是字符串对象还是字符串文字,如何才能使该函数正常工作?

非常感谢您的帮助。

由于您对 Key 模板参数的推导存在冲突,您可以简单地将 Key 参数之一设为非推导上下文。

首先提供一个简单的类型标识结构:

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

然后像这样使用它:

template <template <typename Key, typename Val, typename ...Args> typename C,typename Key, typename Val, typename ...Args>
Val get_or_default(C<Key, Val, Args...> const& my_map, typename I<Key>::type  const &k, Val const& v)
{
    typename C<Key, Val, Args...>::const_iterator const it = my_map.find(k);
    return (it != my_map.end()) ? it->second : v;
}

你可以稍微简化一下。删除模板模板参数名称,因为无论如何都不会使用它们。此外,您可以使用 auto 作为迭代器类型。此外,可变参数似乎没有用于任何目的。

template <template <typename, typename> typename C, typename Key, typename Val>
Val get_or_default(C<Key, Val> const& my_map, typename I<Key>::type const &k, Val const& v)
{
    auto const it = my_map.find(k);
    return (it != my_map.end()) ? it->second : v;
}

这是一个有效的 demo

这应该适合你:

template<class C, class Key, class Val>
Val get_or_default(C const& mp, Key const& k, Val const& v)
{
    typename C::const_iterator it = mp.find(k);
    return (it != mp.end()) ? it->second : v;
}

如果您想要更好的类型限制和错误消息,并且 c++ 20 是一个选项,那么概念是可行的方法