当前位置: 首页 > 知识库问答 >
问题:

影响模板过载分辨率的优化级别

韩乐湛
2023-03-14

我遇到了关于模板重载解析的有趣行为,在发布版本和调试版本之间有所不同。我希望能够理解编译器/链接器使用的规则,这些规则使它以这种方式运行。< br >我尝试了一下,这是我想到的:

S. h

#pragma once

#include <cstdint>
#include <iostream>
enum class Enumeration : uint32_t {
    A = 0,
    B
};
struct S {
    template<typename T>
    bool func(Enumeration en) {
        std::cout << "enum nonspec\n";
        return func<T>(static_cast<uint32_t>(en));
    }

    template<typename T>
    bool func(uint32_t en) {
        std::cout << "uint32_t nonspec\n";
        return func<T>(en);
    }
};

S.cpp

#include "S.h"
template<>
bool S::func<float>(uint32_t en) {
    std::cout << "float specialization\n";
    return en;
}

template<>
bool S::func<uint32_t>(uint32_t en) {
    std::cout << "uint32_t specialization\n";
    return en - 1;
}

main.cpp

#include "S.h"

int main() {
    S s;
    Enumeration a = Enumeration::B;
    s.func<float>(a);
    return 0;
}

我尝试编译相应的编译单元(S.cpp.o,main.cpp.o和生成的二进制文件)。我发现结果完全取决于main.cpp.o编译的优化水平。

使用 -O0 时,输出为
枚举非规范
浮点特化

使用 -O1 时,输出为
枚举非规范
uint32_t非规范
uint32_t非规范
浮点特化

使用-O2-O3,输出是
枚举nonspec
,然后是无限递归uint32_tnonspec

我已经检查了对象文件,-O0
00000000000000000 W bool S::func

使用的编译器:gcc版本7.5.0(Ubuntu 7.5.0-3ubuntu1~18.04)
使用的链接器:ldd(Ubuntu GLIBC 2.27-3ubuntu1.3)2.27

我想我明白会发生什么,但我想知道这种行为是否有任何规则。


共有1个答案

谷涵容
2023-03-14

C 标准要求在使用之前声明所有模板特化。

见[temp.expl.spec]/6:

如果模板、成员模板或类模板的成员被显式专门化,则应在第一次使用该专门化之前声明该专门化,该专门化将导致隐式实例化,在出现此类使用的每个翻译单元中;不需要诊断。

如果程序未提供显式专门化的定义,并且专门化的使用方式可能导致隐式实例化,或者成员是虚拟成员函数,则程序格式错误,不需要诊断。

所以这个程序是不正确的,NDR。编译器不需要发出错误或警告,在这种情况下发生什么也没有限制,因为它永远不会发生。因此,无论它“起作用”、“似乎起作用”还是“不起作用”,都是纯粹的意外。

可能发生的情况是编译器上的html" target="_blank">优化内联了调用,否则不会,这允许链接器在链接时仍然找到特化。

 类似资料:
  • 我试图为我的编程类写一个优先级队列,但继续得到以下错误:PriorityQueue.cpp: 7:1:错误:“PriorityQueue::PriorityQueue”命名构造函数,而不是类型PriorityQueue.cpp: 7:1:错误:和PriorityQueue没有模板构造函数 我已经做了几个小时了,不知道出了什么问题。以下是它所指的代码:

  • 好的,这里有一个奇怪的问题,我有问题(用gcc btw编译) 下面是用于命令提示的Mandelbrot分形生成器的源代码。我以前做过这项工作,我想加快自己的测试速度,看看我能以多快的速度生成命令提示符中实际生成Mandelbrot分形所需的代码。我经常这样做是为了给自己找点乐子 不管怎样,我遇到了一个新问题,我不太明白问题是什么。当分形呈现时,无论我设置了多少次迭代或什么转义值,它都将始终显示为椭

  • GCC接受以下代码: 但是clang拒绝它并带有以下错误: 这似乎表明GCC和clang在重载解析期间执行某些操作的顺序有所不同。GCC似乎在尝试实例化模板候选者的返回类型之前抛弃了模板候选者,因为第二个参数(vs.)中的类型不匹配,而clang似乎反过来做。 谁是对的? 我相信这个问题对模板库的作者有着重要的意义。具体来说,如果clang是正确的,那么模板的作者将不得不做额外的工作,将错误转化为

  • 问题内容: 当网站输出到客户端时,我正在尝试优化网站的大小。缓存时,我分别只有1.9MB和29KB。问题在于,第一次加载包含的图像对于移动设备而言并未经过优化。它具有1080p分辨率。 因此,我正在寻找一种方法,该方法允许我首先加载低分辨率版本(),一旦网站加载完毕,请使用高分辨率版本- 甚至分辨率接近所用设备的分辨率版本(或只是) 。 就像每个人都期望的那样,使用CSS设置背景。它应用于主体,整

  • 功能介绍 获取百度移动统计平台的全部屏幕分辨率列表 接口 https://openapi.baidu.com/rest/2.0/mtj/svc/config/getScreenList?access_token={ACCESS_TOKEN} 请求参数 参数名 类型 描述 样例 access_token string 用户登入后获取的token 1.a6b7dbd428f731035f771b8d

  • iPhone 分辨率汇总 机型分辨率 iPhone型号 pt scale px 宽高比 statusBar tabBar iPhone 4s 320 * 480 2 1.5 20 49 iPhone 5 320 * 568 2 1.775 ↑ ↑ iPhone 5s 320 * 568 2 1.775 ↑ ↑ - - - - - - - iPhone 6/7/8 375 * 667 2 1.778