C++ 为什么不是';t这个std::string\u是否查看常量表达式?

C++ 为什么不是';t这个std::string\u是否查看常量表达式?,c++,c++17,constexpr,C++,C++17,Constexpr,我对constexpr编程比较陌生,正在尝试在constexpr上下文中对string\u视图对象进行一些基本操作。在我的例子中,所有的字符串在我的源代码中都以文本开头,所以看起来它们应该是常量表达式。我发现我可以从字符串文本构建constexpr string\u视图,没有任何问题 但是,如果我尝试调用一个constepr函数,该函数接受一个带有字符串文本的string\u视图参数,则编译失败。请参见下面的示例(): #包括 //这不是编译;编译器抱怨“sv”不是一个常量表达式 constex

我对
constexpr
编程比较陌生,正在尝试在
constexpr
上下文中对
string\u视图
对象进行一些基本操作。在我的例子中,所有的字符串在我的源代码中都以文本开头,所以看起来它们应该是常量表达式。我发现我可以从字符串文本构建
constexpr string\u视图
,没有任何问题

但是,如果我尝试调用一个
constepr
函数,该函数接受一个带有字符串文本的
string\u视图
参数,则编译失败。请参见下面的示例():

#包括
//这不是编译;编译器抱怨“sv”不是一个常量表达式
constexpr bool foo(std::string_view sv)
{
constexpr auto it=sv.find('b');
返回它!=sv.end();
}
//不过,这编译得很好
constexpr std::string_视图栏(“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');
:在函数“constexpr bool foo(std::string_view)”中:
:5:32:在“sv.std::basic_string_view::find”((int)“b”),0)的“constexpr”扩展中
:5:36:错误:“sv”不是常量表达式
constexpr auto it=sv.find('b');

为什么
foo()
string\u视图
参数未被视为常量表达式?

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

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


顺便说一下,这里不应该使用名称
it
,因为它具有误导性
std::string_view::find
返回一个索引,而不是迭代器。

供参考:在函数内部,其参数从不被视为constexpr。如果您将constexpr参数传递给它,那么唯一可以成为constexpr的就是返回值。也就是说,
basic\u string\u view::find
constexpr
。您刚刚添加了过时的
constexpr
“使用constexpr做任何有用的事情都非常困难”不,我是指其他东西。函数总是像参数不是constexpr一样工作,但如果它们实际上是constexpr,则调用方可以在constexpr上下文中使用返回值。(假设函数不做任何在编译时无法完成的事情。)这是有道理的,只是感觉很尴尬。这是一个有趣的例子,但我希望能够在
constexpr
上下文中进一步使用
find()
的结果,例如
static\u assert(ind>=0)
。为了使其可编译,我需要将
constexpr
的任何强制执行从函数体中取出,因此需要在调用堆栈的更高层执行,在那里我可以强制执行返回值为
constexpr
。有什么办法可以简化这一点吗?我更喜欢在一个地方实现这种逻辑,而不是在每个地方用不同的文字调用函数。也许这些就是C++20的
consteval
解决的那种问题。@JasonR是的,我认为
consteval
是这种情况下需要的。在C++17中,我认为没有任何方法可以强制执行
std::string_view
参数的constexpress。您甚至不能将这样的参数升级为模板参数,因为它不满足作为模板参数类型的要求。我还没有在实践中使用
constepr
函数积累太多经验,但这听起来有可能无法保证一个
constexpr
函数的parameter必须可以从另一个
constexpr
函数计算,或者该函数应该直接插入“调用”中吗?啊,对不起。我刚刚看到提到的
consteval