为什么这个 std::string_view 不是常量表达式?

Why isn't this std::string_view a constant expression?

我对 constexpr 编程比较陌生,正在尝试在 constexpr 上下文中对 string_view 对象进行一些基本操作。在我的例子中,所有字符串在我的源代码中都以文字开头,所以它们似乎应该是常量表达式。我发现我可以毫无问题地从字符串文字构造 constexpr string_view

但是,如果我尝试调用带有字符串文字的 string_view 参数的 constexpr 函数,则编译会失败。请参阅以下示例 (Compiler Explorer link):

#include <string_view>

// this doesn't compile; the compiler complains that `sv` is not a constant-expression
constexpr bool foo(std::string_view sv) 
{
    constexpr auto it = sv.find('b'); 
    return it != sv.end();
}

// this compiles just fine, though
constexpr std::string_view bar("def");

int main()
{
    foo("abc");
}

gcc 8.3 提供以下错误:

<source>: In function 'constexpr bool foo(std::string_view)':
<source>:5:32:   in 'constexpr' expansion of 'sv.std::basic_string_view<char>::find(((int)'b'), 0)'
<source>:5:36: error: 'sv' is not a constant expression
     constexpr auto it = sv.find('b');

为什么 foo()string_view 参数不被视为常量表达式?

constexpr 对象的值必须始终 是编译时常量。由于函数 foo 无法控制传递给它的参数,因此参数 sv 不能被视为常量表达式(调用者可以传递非常量表达式参数),因此不能用于将 it 定义为 constexpr 对象。

constexpr 说明符可以简单地从 it 的定义中删除,然后 foo 将编译并且甚至可以生成常量表达式(前提是参数是常量表达)。 (允许常量表达式引用非 constexpr 对象,但不允许调用非 constexpr 函数。)

顺便说一句,it 这个名字不应该在这里使用,因为它具有误导性。 std::string_view::find returns 索引,不是迭代器。