gpt4 book ai didi

c++ - 将本地字符串参数作为对 const 的引用传递给 constexpr 函数?为什么这是合法的?

转载 作者:搜寻专家 更新时间:2023-10-31 01:00:05 25 4
gpt4 key购买 nike

constexpr 函数 只接受文字类型 的参数。 string 类的对象本身不是文字类型,但指针(标量类型)或引用是文字类型。因此,对字符串的引用是文字类型。

此外,constexpr 函数 仅返回常量表达式,如果它的参数也是常量表达式

"The scale* function will return a constant expression if its argument is a constant expression but not otherwise:"
Source: The C++ Primer, 5th edition

scale 在这种情况下 is_shorter()

现在我在这里将对字符串的两个引用传递给一个 constexpr 函数,它不保留在固定地址(全局或静态),而是保留在可变地址(本地)。因此两个参数都不应该是常量表达式。
constexpr 函数 的结果被分配给一个constexpr bool

#include <iostream>
#include <string>
#include <type_traits>
using namespace std;

/*
* it isn't possible to define is_shorter as constexpr function
* 1. string is not a literal type, but can be passed as pointer or reference,
* which are literal types.
* 2. the member function size() is not a constexpr function
*
*/

// compare the length of two strings
constexpr bool is_shorter(const string& s1, const string& s2) {
// compiler message from gcc: 'error: call to non-constexpr function'
// return s1.size() < s2.size();

// compare addresses of pointers, which is legal or illegal but useless, because
// both parameters are local objects and not stored at fixed addresses.
return &s1 != &s2;
}

int main() {
string shrt = "short";
string longer = "longer";

cout << "address of shrt " << &shrt << "\n";
cout << "address of longer " << &longer << "\n";

constexpr bool state = is_shorter(shrt, longer);
if (state) {
cout << "shrt is shorter\n";
} else {
cout << "longer is longer\n";
}

cout << "string " << is_literal_type<string>::value << "\n";
cout << "string& " << is_literal_type<string&>::value << "\n";
cout << "string* " << is_literal_type<string*>::value << "\n";
return 0;
}

编译:

$ g++ -o ex646 ex646.cpp -std=gnu++11 -Wall -Wpedantic

运行:

$ ./ex646
address of shrt 0x7ffd39e41a50 # every time different
address of longer 0x7ffd39e41a40 # every time different, always 0x10 more than &shrt
shrt is shorter
string 0
string& 1
string* 1

编译器如何比较两个字符串的地址?它们在程序的每个运行时都是不同的,而它们的相对位置保持不变。这种用法的关键是至少它们彼此的相对位置保持不变吗?

2015-08-12更新
在撰写本文时,这看起来像是 ISO 标准的“不断评估规则中的错误”(如果我错了,请纠正我)。看这个discussion在 isocpp.org 列表中。因此,这不应该是 GCC 和 CLANG 中的编译器错误。

谢谢你!

最佳答案

据我所知,这看起来像是某种编译器扩展或错误。 C++11 通过缺陷报告进行了调整,以允许将引用视为文字类型,而不管它引用的变量是否为文字类型。但是,引用常量表达式应该引用静态存储持续时间的对象,类似于地址常量表达式。

C++11 标准草案告诉我们什么情况下指针可以被认为是相等的:

Two pointers of the same type compare equal if and only if they are both null, both point to the same function, or both represent the same address (3.9.2).

因此在您的情况下,编译器可以简单地推断出 != 属于哪种情况,但我看不出有什么可以避免这种情况下的常量表达式要求。

引用 5.19 [expr.const] 告诉我们:

an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization, initialized with a constant expression

这是由 defect report 1454 修改的更改如下:

an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either

  • it is initialized with a constant expression or
  • it is a non-static data member of an object whose lifetime began within the evaluation of e

但在任何一种情况下都足以使这种情况不是常量表达式。

A reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function. An address constant expression is a prvalue core constant expression of pointer type that evaluates to the address of an object with static storage duration, to the address of a function, or to a null pointer value, or a prvalue core constant expression of type std::nullptr_t.

这些都不适用于您的案例中的自动变量。

引用最初不是文字而是 defect report 1195 其中说:

7.1.5 [dcl.constexpr] paragraph 3 is overly restrictive in requiring that reference parameter and return types of a constexpr function or constructor must refer to a literal type. 5.20 [expr.const] paragraph 2 already prevents any problematic uses of lvalues of non-literal types, and it permits use of pointers to non-literal types as address constants. The same should be permitted via reference parameters and return types of constexpr functions.

并更改 3.9 [basic.types] 部分,该部分在 N3337 草案 C++11 标准中说:

A type is a literal type if it is:

[...]

  • a reference type referring to a literal type; or

到:

  • a reference type; or

关于c++ - 将本地字符串参数作为对 const 的引用传递给 constexpr 函数?为什么这是合法的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31922063/

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