首页 > 解决方案 > 如何对复杂的模板化函数进行显式实例化?和相关的智能感知错误

问题描述

更新 1:将代码替换为独立构建的代码以使其更清晰

更新 2:部分修复了基于 @Jarod42 评论的实例化问题,但仍然失败

我有一些代码想要以不区分大小写的方式搜索带有字符串键的字典。完整代码如下。

所示代码编译、链接和工作,没有任何警告、错误或问题。

如果我取消注释显式实例化模板的行,那么我会得到

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

标签: c++templatescontainers

解决方案


我有这段代码来显式实例化模板:

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

推荐阅读