gpt4 book ai didi

c++ - const QString& 的显式模板特化导致未解析的外部

转载 作者:行者123 更新时间:2023-11-30 04:29:52 25 4
gpt4 key购买 nike

#include <QFile>
#include <QString>

// this is some sort of low-level C function
void lowLevelOpenFD(int fd)
{
qDebug("Opened by fd: %d", fd);
}

// as well as this one
void lowLevelOpenName(const char *name)
{
qDebug("Opened by name: %s", name);
}

// this is a wrapper around low-level functions
template<typename FileId>
void callLowLevelOpen(FileId id);

template<>
void callLowLevelOpen(const QString &fileName)
{
lowLevelOpenName(QFile::encodeName(fileName).constData());
}

template<>
void callLowLevelOpen(int fd)
{
lowLevelOpenFD(fd);
}

// this is the function where the most stuff happens
template<typename FileId>
void openInternal(FileId id)
{
// lots of useful stuff goes here
// now we call one of the two low level functions
callLowLevelOpen(id);
// more useful stuff
}

// this is high-level interface to the "open by name" function
void openFile()
{
QString name = "file";
openInternal(name);
}

// this is high-level interface to the "open by FD" function
void openFile(int fd)
{
openInternal(fd);
}

int main()
{
openFile();
openFile(17);
return 0;
}

问题是上面的例子导致了

error LNK2019: unresolved external symbol "void __cdecl callLowLevelOpen<class QString>(class QString)" (??$callLowLevelOpen@VQString@@@@YAXVQString@@@Z) referenced in function "void __cdecl openInternal<class QString>(class QString)" (??$openInternal@VQString@@@@YAXVQString@@@Z)

据我所知,这是因为编译器实例化了 openInternal<QString>()当它从第一个高级重载调用时。好的,所以我想到并修改了代码:

// this is high-level interface to the "open by name" function
void openFile()
{
QString name = "file";
openInternal<const QString&>(name);
}

同样的问题。我以为我告诉编译器实例化 openInternal<const QString&> ,那么为什么它仍然提示 <class QString> ?我也试过这个:

// this is high-level interface to the "open by name" function
void openFile()
{
QString name = "file";
openInternal<const QString&>(static_cast<const QString&>(name));
}

现在这看起来很傻,但仍然行不通。我不能明确地特化 openInternal()一个是因为它太大了,这个模板化的困惑的重点是避免不必要的代码重复。我不能只是重命名低级函数以将它们变成重载函数,因为它们在第三方 C 库中。我唯一能做的就是替换第一个 callLowLevelOpen()特化

template<>
void callLowLevelOpen(QString fileName)
{
lowLevelOpenName(QFile::encodeName(fileName).constData());
}

然后就可以了。性能损失几乎为零,因此这是一个完全有效的解决方法,但我只想了解这里发生了什么。

上面的代码只是一个SSCCE,真正的代码是there如果有人感兴趣。此特定问题与 gzopen()/gzdopen() 有关, QuaGzipFilePrivate::open()QuaGzipFile::open()功能。

最佳答案

由于您实际上更改了签名,所以我认为您实际上不想专门化您的函数模板,而是使用重载。这是使用 std::string 的完整测试程序(如果问题也可以在那里重现,我更喜欢只依赖于标准类):

#include <string>

template <typename T> void f(T);
// #define BROKEN
#if defined(BROKEN)
template <> void f(std::string const&) {}
#else
void f(std::string const&) {}
#endif

int main()
{
std::string s;
f(s);
}

如果你#defined BROKEN在此代码中,它将不起作用。

此行为的原因是编译器根据主模板选择重载。这永远不会添加 const&部分。完成此操作后,编译器会查找所选重载的潜在特化。由于这永远不会推断出用于特化的符号,因此不会被拾取。

那为什么是f<std::string const&>(s)不选专业?对我来说,尝试使用 gcc 和 clang。

关于c++ - const QString& 的显式模板特化导致未解析的外部,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9054942/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com