如何对复杂的模板化函数进行显式实例化?和相关的 Intellisense 错误
Posted
技术标签:
【中文标题】如何对复杂的模板化函数进行显式实例化?和相关的 Intellisense 错误【英文标题】:How do I do an explicit instantiation of a complex templated function? and related Intellisense error 【发布时间】:2020-06-11 19:23:35 【问题描述】:更新 1:将代码替换为独立构建的代码以使其更清晰
更新 2:部分修复了基于 @Jarod42 评论的实例化问题,但仍然失败
我有一些代码想要以不区分大小写的方式搜索带有字符串键的字典。完整代码如下。
所示代码编译、链接和工作,没有任何警告、错误或问题。
如果我取消注释显式实例化模板的行,那么我会得到 p>
警告 C4667:'const std::_Tree_const_iterator>>> findKeyIC(const MyMap &,const std::wstring &)':未定义与强制实例化匹配的函数模板
另外,在调用 findKeyIC intellisense 的 FindNameMyMapIC 行中会抱怨:
E0304 没有函数模板“findKeyIC”的实例与参数列表参数类型匹配:(const MyMap, const std::wstring)
我对 Intellisense 问题最感兴趣,但觉得显式实例化问题可能是相关的。
#include <boost/algorithm/string.hpp>
#include <map>
typedef std::map<std::wstring, int> MyMap;
const MyMap gMyMap = L"A", 0, L"B", 1 , L"C", 2 ;
// Cases insensitive comparison of two strings, return true if they match.
// Supports std:string variants and char*/wchar*.
template<class StrType>
inline bool StrIEquals(const StrType& str1, const StrType& str2)
return boost::iequals(str1, str2);
inline bool StrIEquals(const char* const& str1, const char* const& str2)
return (_stricmp(str1, str2) == 0);
inline bool StrIEquals(const wchar_t* const& str1, const wchar_t* const& str2)
return (_wcsicmp(str1, str2) == 0);
// Returns an iterator that refers to the location of an element in a map that has a key equivalent
// to a specified key using case insensitive comparison.
template <typename Key, typename Value, typename Reference, template<typename ...> class Container>
inline auto findKeyIC(const Container<Key, Value>& container, Reference const& key)
auto it = container.cbegin();
for (; it != container.cend(); ++it)
if (StrIEquals((const Key)it->first, (const Key)key))
return it;
return it;
// template const MyMap::const_iterator findKeyIC(const MyMap& container, const std::wstring& key);
int FindNameMyMapIC(const std::wstring& name)
auto it = findKeyIC(gMyMap, name);
if (it != gMyMap.cend())
return it->second;
return -1;
【问题讨论】:
我尝试用 'typename MyMap::const_iterator' 替换模板定义中的 auto 和显式实例化,但它的行为方式相同。 明确地图模板参数比较和分配似乎可以解决智能感知问题,并结合使用显式 const_iterator(上一条评论)将具有显式实例化的探针转换为智能感知警告(函数定义为'findKeyIC' 未找到) 意识到我仍然误解了您如何进行显式实例化, 产生智能感知警告但没有错误的显式实例化是:模板类型名 MyMap::const_iterator findKeyIC(const MyMap& container, std::wstring const& key); 完全明确比较和分配器不会改变这一点 【参考方案1】:我有这段代码来显式实例化模板:
MyMap::const_iterator findKeyIC(const MyMap& container, const std::wstring& key);
不,你声明了非模板函数重载。
我认为智能感知会受到“可变参数”容器的干扰,而 std::map
则不会。
如果可能,我会更改您的地图比较器以比较不区分大小写,因此您可以使用map::find
(对数查找而不是线性搜索)
否则,您可能会这样做:
// Returns an iterator that refers to the location of an element in a map that has a key equivalent
// to a specified key using case insensitive comparison.
template <typename Key, typename Container>
auto findKeyIC(const Container& container, Key const& key)
return std::find_if(container.cbegin(), container.cend(),
[&](const auto& p) return StrIEquals(p.first, key); );
【讨论】:
噢!感谢您发现显式实例化问题,这误导了我。有了这个固定的智能感知,就会像另一个例子一样抱怨。 我试图修复显式实例化并且新代码不起作用,尽管它至少现在抱怨在显式实例化期间无法匹配模板,并且可能提供了 Intellisense 失败原因的线索.我已经更新了问题,希望能让事情更清楚 感谢关于 find_if 的建议,我没遇到过【参考方案2】:可以通过用显式类型替换模板定义中的 auto 并显式列出 std:map 模板可选参数 Compare 和 来修复 Intellisense 错误>分配器.
因此那部分代码变成:
// Returns an iterator that refers to the location of an element in a map that has a key equivalent
// to a specified key using case insensitive comparison.
template <typename Key, typename Value, typename Reference, class Compare, class Allocator, template<typename ...> class Container>
inline typename Container<Key, Value, Compare, Allocator>::const_iterator findKeyIC(const Container<Key, Value, Compare, Allocator>& container, Reference const& key)
auto it = container.cbegin();
for (; it != container.cend(); ++it)
if (StrIEquals((const Key)it->first, (const Key)key))
return it;
return it;
template typename MyMap::const_iterator findKeyIC(const MyMap& container, std::wstring const& key);
此代码编译和链接时没有编译器警告或错误,也没有智能感知错误。
但是,它会在显式模板实例化行中的 findKeyIC 上留下智能感知警告。
找不到“findKeyIC”的函数定义。
【讨论】:
为什么要显式实例化? TBH 我现在不需要它,我这样做是为了帮助诊断我遇到的问题。现在我已经成功地构建了它,没有智能感知或编译器错误,我可以忽略它。以上是关于如何对复杂的模板化函数进行显式实例化?和相关的 Intellisense 错误的主要内容,如果未能解决你的问题,请参考以下文章