为什么gcc8.3似乎试图编译一个未使用的模板函数



考虑(文件名为hello.cpp(这段代码;其思想是设计一个数字类型的安全铸造,而不会丢失或溢出。(我正在将一些代码从MSVC移植到g++(。

#include <cstdint>
#include <iostream>
template<
typename T/*the desired type*/,
typename/*the source type*/ Y
> T integral_cast(const Y& y)
{
static_assert(false, "undefined integral cast");
}
// Specialisation to convert std::uint32_t to double
template<>
inline double integral_cast(const std::uint32_t& y)
{
double ret = static_cast<double>(y);
return ret;
}
int main()
{
std::uint32_t a = 20;
double f = integral_cast<double>(a); // uses the specialisation
std::cout << f;
}

当我使用gcc 8.3通过键入g++ -o hello hello.cpp进行编译时,我会得到错误error: static assertion failed: undefined integral cast

这意味着g++总是在编译未使用的模板代码。

请注意,MSVC编译了这个(这很好,因为它可以让我发现任何我没有考虑过的整体演员阵容专业化(。

很明显我错过了什么。但是什么?

GCC并不是真正"实例化"或"编译"基函数模板。如果是这样的话,您将拥有两个具有相同名称和参数列表的已编译函数。正如@Raymond Chen在评论中指出的那样,GCC被允许但不是必需的,为没有任何有效实例化的模板引发错误。

例如:

template<
typename T/*the desired type*/,
typename/*the source type*/ Y
> T integral_cast(const Y& y)
{
static_assert(sizeof(Y) == 1);
};

不会在您给出的示例中引发错误(因为它有一个有效的实例化,并且没有实例化(。

我怀疑GCC只需要将类型替换到基本模板中以进行重载解析,所以它实际上只需要声明,而不是定义

你可以通过使用一个已删除的定义来获得你想要的行为:

template<
typename T/*the desired type*/,
typename/*the source type*/ Y
> T integral_cast(const Y& y) = delete;

相关内容

最新更新