- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
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/
在 ubuntu gcc 8.0 中: void bar(){} constexpr int foo(int a) { if (a <=0 ) bar(); retur
考虑一个在运行时只包装一个值的类: template class NonConstValue { public: NonConstValue(const Type& val)
在试验 constexpr 函数和模板(以及非类型模板参数)时,我偶然发现了一个现象,我无法理解是哪条规则使它生效。 所以根据 constexpr-s 的规则,我的问题本质上是“为什么会发生这种情况”
我正在阅读 Nicolai M. Josuttis 所著的“C++ 17 The Complete Guide”一书,无法理解以下示例 auto squared1 = [](auto val) con
(使用 g++ 7.0 主干。) 给定以下“类型到值包装”实用程序... template struct type_wrapper { using type = T; }; // "Wraps" a
我编写了一些代码,它能够根据调用站点提供与给定函数关联的字符串(通过函数指针和并行数组的tuple)来分派(dispatch)给函数。 dispatch 函数不直接接受字符串,而是接受 Callabl
如果我想使用一些方便的东西,比如 make_array 我没有机会先声明我的数组,然后再像“早些时候”那样进行定义,因为我的 var 类型不可用定义前。 所以我找到了这个答案: Undefined r
使用 gcc (HEAD 7.0.0 201612) 我惊讶地发现这有效: constexpr long value(const char *definition) { if (definit
我有这个片段。 #include #include struct JustStr { JustStr(const std::string& x) : val(x) {} stati
我找不到任何关于新 C++17 if 初始化语法的信息和“constexpr if”在: http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p01
考虑以下函数: template auto concatenate(std::array &data1, std::array &data2) { std::array result;
假设我有以下对象: #include class Foo { public: constexpr Foo() {}; constexpr std::string foo() cons
我正在尝试使用 https://github.com/gdelugre/literal_ipaddr它说它是一个 C++17 constexpr implementation of inet_addr
我想重新定义unique_ptr用一个特殊的析构函数。因此,我使用以下代码尝试模仿 unique_ptr 的一些构造函数.遗憾constexpr施 worker 员拒绝 build ,我不知道为什么。
我想用结构名称的哈希值初始化一个结构成员。 constexpr uint32_t myHash(const char* const data) { //Some code for hash r
我正在尝试编译 C++ 库(使用 gcc 5.3.1-14ubuntu2)并遇到此类错误: > In file included from > /root/pitchfork/workspace/un
设置: 我有一个使用 SIMD 内部函数的函数,我想在一些 constexpr 函数中使用它。 为此,我需要将其设为 constexpr。但是,SIMD 内在函数没有标记为 constexpr,编译器
这是一个简化的代码示例,旨在生成任意值序列(在 std::iota 的意义上)和在它们之上的不同类别的迭代器: struct delta { template void inc(I&
考虑以下函数: template auto concatenate(std::array &data1, std::array &data2) { std::array result;
我偶然发现了调用非 constexpr 函数的 constexpr 模板函数:在以下代码段中,由于调用了非 constexpr set,bar 无法按预期编译,但 foo 可以编译。谁能告诉我 foo
我是一名优秀的程序员,十分优秀!