C++ 由来自同一模板函数的局部静态变量参数化的模板类型是否应该比较相等?

C++ 由来自同一模板函数的局部静态变量参数化的模板类型是否应该比较相等?,c++,c++17,language-lawyer,C++,C++17,Language Lawyer,考虑以下程序(): 模板 结构是相同的{static constexpr bool value=false;}; 模板 结构是相同的{static constexpr bool value=true;}; 模板 静态constexpr bool是\u-same\u v=是\u-same::value; 使用uintptr_t=无符号长; 模板 结构参数化{int const*member;}; 模板 自动创建(){ 静态常量expr int const I=2; 返回参数化{&I}; } int

考虑以下程序():

模板
结构是相同的{static constexpr bool value=false;};
模板
结构是相同的{static constexpr bool value=true;};
模板
静态constexpr bool是\u-same\u v=是\u-same::value;
使用uintptr_t=无符号长;
模板
结构参数化{int const*member;};
模板
自动创建(){
静态常量expr int const I=2;
返回参数化{&I};
}
int main(){
自动一=创建();
自动二=创建();
如果(是否相同){
return reinterpret_cast(1.member)=reinterpret_cast(2.member)?1:2;
}
返回0;
}
基于n4659(C++17最终工作草案):

§17.4[温度类型]/1

两个模板ID引用相同的类、函数或变量,如果:

  • 它们的模板名称、运算符函数ID或文本运算符ID引用相同的模板和
  • 它们对应的类型模板参数的类型和类型相同
  • 它们相应的整型或枚举型非类型模板参数具有相同的值和
  • 它们对应的指针类型的非类型模板参数引用同一个对象或函数,或者是空指针值
  • 它们对应的指向成员类型的指针的非类型模板参数引用同一个类成员,或者同时是null成员指针值和
  • 它们对应的引用类型的非类型模板参数引用相同的对象或函数,并且
  • 它们对应的模板参数引用同一模板
我希望:

  • 存在单个
    静态constexpr int const I=2的实例create
    的所有实例化,在这种情况下
    decltype(一)
    引用与
    delctype(二)
    相同的类
  • 或者有一个
    static constexpr int const I=2的实例对于
    的每个实例化创建
    ,在这种情况下,两者引用不同的类
然而,当使用GCC或Clang(产生二进制的任何版本)时,main的结果是
2
指示:

  • one
    two
    的类相同
  • 然而,
    create():I
    的另一个实例
程序集列表确认创建了两个实例:
\uzz6createisedave1i
(aka
create():I
)和
\uzz6createiiedave1i
(aka
create():I

根据C++17标准,
one
two
的类型是否相同?



有趣的变化:将
=2
替换为
=sizeof(T)
会导致类型不同(参见)。

根据[intro.object](emphasis我认为clang/gcc的行为违反了标准(可能是不合适的,好像优化了一样?)

除非对象是位字段或大小为零的子对象,否则该对象的地址就是第一个对象的地址 它占用的字节数。两个生命周期重叠且不是位字段的对象可能具有相同的地址,如果 一个嵌套在另一个中,或者至少有一个是大小为零的子对象,并且它们的类型不同; 否则,它们具有不同的地址并占用不相交的存储字节

由于对象之间不嵌套,也不是大小为零的子对象,因此不允许它们具有相同的地址

此处的(非规范性)脚注也与此相关:

根据“仿佛”规则,允许实现在同一机器地址存储两个对象,或者不存储对象 如果程序无法观察到差异,则根本不需要

但是,在这种情况下,当对象位于相同的机器地址时(即使我们可以保证它们的值相同),存在行为差异,因此它们不应该占用相同的地址


需要注意的是,MSVC不考虑优化级别,我认为这是正确的行为。

在探索将
char const*
作为模板参数传递时发现,如中所示。出于好奇,报告为。让我们看看GCC开发人员的意见是什么。不管怎样,都有一个bug。@passer:很好的发现。出于某种原因,没有想到测试主干……并且也报告了;用链接器的奖金来奖励clang。哦!我没有意识到我可以用godbolt测试MSVC!这是一个非常有趣的数据点,是的,我也相信结果应该是0——尽管我可以接受1,因为它至少在类型域和值域之间是一致的。根据我的Clang bug报告中的评论,这是在(报告提交当天)修复的。