C++11 是全局变量constexpr的地址吗?

C++11 是全局变量constexpr的地址吗?,c++11,language-lawyer,C++11,Language Lawyer,考虑以下几点 struct dummy{}; dummy d1; dummy d2; template<dummy* dum> void foo() { if (dum == &d1) ; // do something else if (dum == &d2) ; // do something else } 一切都按预期进行。但以下情况并非如此 constexpr dummy* dum_ptr = &d

考虑以下几点

struct dummy{};

dummy d1;
dummy d2;

template<dummy* dum>
void foo()
{
    if (dum == &d1)
        ; // do something
    else if (dum == &d2)
        ; // do something else
}
一切都按预期进行。但以下情况并非如此

constexpr dummy* dum_ptr = &d1;
foo<dum_ptr>();
在visual studio中,但不是在G++中,因为

注意:模板参数扣除/替换失败:
错误:
&dum\u ref
不是
dummy*
的有效模板参数,因为它不是变量的地址

foo<&dum_ref>();
foo();
编辑:

因为C++17,
std::addressof
被标记为constexpr,所以我想它应该可以工作。

GCC在这个问题上是正确的

表达式肯定是s*,因为它们被分配给
constepr
变量。但是,在c++14之前,指针模板参数的允许范围还有其他限制

C++14草案N4140[临时参数非类型] 1非类型、非模板参数的模板参数应为以下参数之一:

  • 对于整型或枚举型的非类型模板参数,为 模板参数;或
  • 非类型模板参数的名称;或
  • 一种常量表达式(5.19),用于指定具有静态存储持续时间和外部或内部数据的完整对象的地址 联动装置或具有外部或内部联动装置的功能,包括 函数模板和函数模板ID,但不包括非静态 类成员,表示为(忽略括号)
    &id表达式
    ,其中id表达式是对象的名称
    或 函数,但如果名称引用 函数或数组,如果相应的 模板参数是一个参考;或
  • 计算为空指针值的常量表达式(4.10);或 计算结果为空成员指针值的常量表达式(4.11);或 指向构件的指针,如5.3.1所述;或 std::nullptr\t类型的常量表达式
对于
foo()

c++17中取消了这些限制以允许任何constexpr,因此它在那里工作:

C++17草案N4606-14.3.2模板非类型参数[temp.arg.nontype] 1非类型模板参数的模板参数应为 类型的转换常量表达式(5.20) 模板参数。对于引用的非类型模板参数或 指针类型,常量表达式的值不应引用 (或对于指针类型,不应为的地址):

  • (1.1)子对象(1.8)
  • (1.2)临时物体(12.2)
  • (1.3)字符串文字(2.13.5)
  • (1.4)typeid表达式(5.2.8)的结果,或
  • (1.5)预定义的函数变量(8.4.1)
与往常一样,clang会给出最好的错误消息:



*(参见地址常量表达式和参考常量表达式)

foo()在g++中也不起作用。很有趣。我用
-std=c++1z
试过了,效果不错,但你是对的。它不能与模板中的
-std=c++14
一起工作。可能是
伪const*dum
伪constepr*dum
?我非常惊讶。它如何与位置无关代码(PIC)、全局偏移表(GOT)和过程链接表(PLT)一起工作?这些地址有时不是只能在运行时定义吗?这个constexpr地址有什么魔力?
constexpr dummy& dum_ref = d1;
foo<&dum_ptr>();
foo<&dum_ref>();