另一个奇怪的编译器错误:调用一个给出未定义引用的模板化函数

Another strange compiler error: calling a templated function which gives undefined referenes

本文关键字:未定义 一个 引用 函数 编译器 错误 调用 另一个      更新时间:2023-10-16

到目前为止,一切顺利。但是,出现了一些问题。

首先,当我调用以下内容时:

const bool bppExists = CheckMapForExistingEntry< std::string, int >( mConfigValues, "bpp" );

我得到以下信息:

error: undefined reference to `bool CheckMapForExistingEntry<std::string, int>(std::map<std::string, int, std::less<std::string>, std::allocator<std::pair<std::string const, int> > > const&, std::string const&)'

还有其他三个发生这种情况的例子。该函数如下所示:

声明

template < class Key, class Value >
bool CheckMapForExistingEntry( const std::map< Key, Value >& map, const std::string& key );

定义

template < class Key, class Value >
bool CheckMapForExistingEntry( const std::map< Key, Value >& map, const std::string& key )
{
    typename std::map< Key, Value >::iterator it = map.lower_bound( key );
    bool keyExists = ( it != map.end && !( map.key_comp() ( key, it->first ) ) );
    if ( keyExists )
    {
        return true;
    }
    return false;
}

那么,这里发生了什么?我包含包含函数声明的头文件,但它仍然不起作用。据此,我应该省略模板参数的值,只传递key_type,但是这也拒绝工作。

例如:

CheckMapForExistingEntry< std::string >( someMap, "somekey" ); //error

您不能轻松地在标头和源文件之间拆分声明和模板的定义;因此模板通常在标头中定义。例如,请参阅"为什么模板只能在头文件中实现?

此外,在这种情况下,您无需显式提供任何类型参数:

CheckMapForExistingEntry(m, "x");

KeyValue的类型可以从map类型自动推导出来。

请注意,您的函数可以显著缩短,例如:

template < class Key, class Value >
bool contains(const std::map<Key, Value>& map, const std::string& key) {
    return map.find(key) != map.end();
}

此外,还可以通用化 key 参数的类型,使函数更易于重用。

相关文章: