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视图
参数未被视为常量表达式?aconstepr
对象的值必须始终是编译时常量。由于函数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
。