gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 22:39:20 24 4
gpt4 key购买 nike

考虑以下

struct dummy{};

dummy d1;
dummy d2;

template<dummy* dum>
void foo()
{
if (dum == &d1)
; // do something
else if (dum == &d2)
; // do something else
}

现在可以调用 foo像这样
foo<&d1>();
foo<&d2>();

一切都按预期工作。但以下不
constexpr dummy* dum_ptr = &d1;
foo<dum_ptr>();

来自 Visual Studio 的这个错误

error C2975: dum_ptr: invalid template argument for foo, expected compile-time constant expression



虽然这有效
constexpr dummy& dum_ref = d1;
foo<&dum_ptr>();

在 Visual Studio 中,但不在 G++ 中,因为

note: template argument deduction/substitution failed:
error: & dum_ref is not a valid template argument for dummy* because it is not the address of a variable

foo<&dum_ref>();


编辑:
从 C++17 开始, std::addressof被标记为 constexpr,所以我猜它应该可以工作。

最佳答案

GCC 在这一点上是正确的。

表达式肯定是 constant-expression s*,因为它们被分配给 constexpr多变的。但是,在 c++14 之前,指针模板参数允许的内容有额外的限制。

C++14 draft N4140 [temp.arg.nontype]

1 A template-argument for a non-type, non-template template-parameter shall be one of:

  • for a non-type template-parameter of integral or enumeration type, a converted constant expression (5.19) of the type of the template-parameter; or
  • the name of a non-type template-parameter; or
  • a constant expression (5.19) that designates the address of a complete object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as &id-expression, where the id-expression is the name of an object or function, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or
  • a constant expression that evaluates to a null pointer value (4.10); or a constant expression that evaluates to a null member pointer value (4.11); or a pointer to member expressed as described in 5.3.1; or a constant expression of type std::nullptr_t.


对于 foo<dum_ptr>() , dum_ptr不表示为 &name , 对于 foo<&dum_ref>() , dum_ref不是对象的名称,而是对对象的引用的名称,因此两者都不允许作为模板参数。

这些限制在 c++17 中被取消以允许任何 constexpr,这就是它在那里工作的原因:

C++17 draft N4606 - 14.3.2 Template non-type arguments [temp.arg.nontype]

1 A template-argument for a non-type template-parameter shall be a converted constant expression (5.20) of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):

  • (1.1) a subobject (1.8),
  • (1.2) a temporary object (12.2),
  • (1.3) a string literal (2.13.5),
  • (1.4) the result of a typeid expression (5.2.8), or
  • (1.5) a predefined __func__ variable (8.4.1).


像往常一样,clang 给出了最好的错误信息:
https://godbolt.org/g/j0Q2bV

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

关于c++11 - 是全局变量 constexpr 的地址吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41085202/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com