为什么 gcc8.3 似乎试图编译未使用的模板函数?
Why does gcc8.3 appear to attempt to compile an unused template function?
考虑(文件名是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;
}
当我通过键入 g++ -o hello hello.cpp
使用 gcc 8.3 进行编译时,出现错误 error: static assertion failed: undefined integral cast
。
这意味着 g++ 总是在编译未使用的模板代码。
请注意,MSVC 对此进行了编译(这很好,因为它允许我发现任何我没有考虑过的整体转换专业化)。
显然我遗漏了什么。但是什么?
GCC 并不是真正的 "instantiating" 或 "compiling" 基本函数模板。如果是,您将拥有两个具有相同名称和参数列表的已编译函数。正如@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;
考虑(文件名是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;
}
当我通过键入 g++ -o hello hello.cpp
使用 gcc 8.3 进行编译时,出现错误 error: static assertion failed: undefined integral cast
。
这意味着 g++ 总是在编译未使用的模板代码。
请注意,MSVC 对此进行了编译(这很好,因为它允许我发现任何我没有考虑过的整体转换专业化)。
显然我遗漏了什么。但是什么?
GCC 并不是真正的 "instantiating" 或 "compiling" 基本函数模板。如果是,您将拥有两个具有相同名称和参数列表的已编译函数。正如@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;