无论我传递的是字符串文字还是字符串对象,我如何才能让这个函数模板起作用?
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 是一个选项,那么概念是可行的方法
我有以下函数模板,它采用任何类型的映射和 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 是一个选项,那么概念是可行的方法