constexpr说明noexcept符是否意味着函数的说明符?对类似问题的回答对说明者说"是" inline,但Eric Niebler的文章让我想知道对当前问题的可能答案.在我看来,答案取决于使用constexpr函数的上下文:是常量表达式上下文还是运行时上下文,即在编译时是否已知函数的所有参数.
我希望答案是"是",但简单的检查表明情况并非如此.
constexpr
bool f(int) noexcept
{
return true;
}
constexpr
bool g(int)
{
return true;
}
static_assert(noexcept(f(1)));
static_assert(noexcept(g(2))); // comment this line to check runtime behaviour
#include <cassert>
#include <cstdlib>
int
main(int argc, char * [])
{
assert(noexcept(f(argc)));
assert(noexcept(g(argc)));
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud) 在C++中,您可以将许多内容声明为constexpr:变量,函数(包括成员函数和运算符),构造函数,以及自C++ 1z以来的if语句和lambda表达式.但是,声明析构函数会 constexpr导致错误:
struct X {
constexpr ~X() = default; // error: a destructor cannot be 'constexpr'
};
Run Code Online (Sandbox Code Playgroud)
我的问题:
constexpr?constexpr吗?~X() = default;),它会自动constexpr吗?是否有可能根据C++ 11中的C++ 11表达式是否为常量表达式(即constexpr)生成编译时布尔值?关于SO的几个问题与此有关,但我在任何地方都没有看到直接答案.
使用新的轻松的C++ 14 constexpr规则,编译时编程变得更具表现力.我想知道标准图书馆是否也会升级以便利用.特别是std::initializer_list,std::pair,std::tuple,std::complex,std::bitset和std::array看起来像总理候选人须注明constexpr批发.
问题:
constexpr?constexpr?<cmath>和<algorithm>标记的功能constexpr?我正在将一个C++ 14- constexpr代码库从Clang 移植到最新的g ++ - 5.1.考虑以下简化的本地bitset类的代码片段,自Clang 3.3(现在差不多2年!)以来,它已经正确编译了.
#include <cstddef>
template<std::size_t>
class bitset;
template<std::size_t N>
constexpr bool operator==(const bitset<N>& lhs, const bitset<N>& rhs) noexcept;
template<std::size_t N>
class bitset
{
friend constexpr bool operator== <>(const bitset<N>&, const bitset<N>&) noexcept;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <-- error from this piece
};
template<std::size_t N>
constexpr bool operator==(const bitset<N>& /* lhs */, const bitset<N>& /* rhs */) noexcept
{
return true;
}
int main() {}
Run Code Online (Sandbox Code Playgroud)
活生生的例子在Wandbox.但是,g ++ - 5.1和当前的trunk版本会出错:
朋友模板专业化的声明中不允许'constexpr'
问题:这是一个已知的g ++错误还是Clang不符合最新标准?
注意 …
在下面的示例中,我可以从lambda内部访问constexpr变量x,y而无需显式捕获它.如果x未声明为,则无法执行此操作constexpr.
是否有适用constexpr于捕获的特殊规则?
int foo(auto l) {
// OK
constexpr auto x = l();
auto y = []{return x;};
return y();
// NOK
// auto x2 = l();
// auto y2 = []{ return x2; };
// return y2();
}
auto l2 = []{return 3;};
int main() {
foo(l2);
}
Run Code Online (Sandbox Code Playgroud) 在您尝试阅读整篇文章之前,请了解:
fameta::counter类中,以解决一些剩余的怪癖。你可以在 github 上找到它;自从 Filip Roséen 在 2015 年发现/发明了通过友元注入编译时间计数器的黑魔法是在 C++ 中,我一直对这个设备有点着迷,所以当 CWG决定功能必须去时,我很失望,但仍然充满希望可以通过向他们展示一些引人注目的用例来改变他们的想法。
然后,几年前,我决定再看一遍,以便uberswitch es可以嵌套 - 在我看来,这是一个有趣的用例 - 只是发现它不再适用于新版本的可用的编译器,即使问题 2118是(现在仍然是)处于打开状态:代码会编译,但计数器不会增加。
该问题已在 Roséen 的网站和最近的 stackoverflow 上报告:Does C++ support compile-time counters?
我想了解编译器发生了什么变化,使看似仍然有效的 C++ 不再起作用。为此,我在互联网上广泛搜索,寻找有人谈论它,但无济于事。所以我开始尝试并得出了一些结论,我在这里提出这些结论是希望能从这里的知识渊博的人那里得到反馈。
为了清楚起见,我在下面展示了 Roséen 的原始代码。有关其工作原理的说明,请参阅他的网站:
template<int N>
struct flag {
friend constexpr int adl_flag …Run Code Online (Sandbox Code Playgroud) c++ counter friend-function argument-dependent-lookup constexpr
取以下合法代码:
bool bar();
template <class T>
constexpr bool foo(T t) {
if (t>0) {
return true;
}
return bar();
}
int main() {
//constexpr bool cb1 = foo(-1); // error as expected because it would attempt to call bar()
constexpr bool cb2 = foo(1); // ok
}
Run Code Online (Sandbox Code Playgroud)
因此,只要我们没有在编译时评估上下文中遇到非 constexpr 代码路径,我们的 constexpr 就形成了良好的格式。整洁的!
但是,如果我应用相同的实际概念,但碰巧在条件代码路径中包含非文字类型,例如std::string,则标准说不:
#include <string>
bool bar(std::string);
template <class T>
constexpr bool foo(T t) {
if (t>0) {
return true;
}
std::string s = "abc";
return bar(s); …Run Code Online (Sandbox Code Playgroud) P0292R1 constexpr如果已包含在内,正在进行 C++ 17.它似乎很有用(并且可以取代SFINAE的使用),但关于static_assert形成不良的评论,假分支中不需要诊断会让我害怕:
Disarming static_assert declarations in the non-taken branch of a
constexpr if is not proposed.
void f() {
if constexpr (false)
static_assert(false); // ill-formed
}
template<class T>
void g() {
if constexpr (false)
static_assert(false); // ill-formed; no
// diagnostic required for template definition
}
Run Code Online (Sandbox Code Playgroud)
我认为它是完全禁止static_assert在constexpr内部使用if(至少是假/非分支,但实际上这意味着它不是一个安全或有用的事情).
这是如何从标准文本中产生的?我发现static_assert在提案中没有提到措辞,并且C++ 14 constexpr函数允许static_assert(cppreference的详细信息:constexpr).
是否隐藏在这个新句子中(6.4.1之后)?:
当constexpr if语句出现在模板化实体中时,在封闭模板或通用lambda的实例化期间,不会实例化丢弃的语句.
从那以后,我认为它也是禁止的,不需要诊断,调用调用图中某个地方可能调用的其他constexpr(模板)函数static_assert.
底线:
如果我的理解是正确的,那么对于constexpr …
为什么此代码会返回警告
警告:ISO C++禁止将字符串常量转换为'char*'[ - WRrite-strings]
如果
在对象声明或非静态成员函数中使用的constexpr说明符(直到C++ 14)暗示const.函数或静态成员变量(自C++ 17)声明中使用的constexpr说明符暗示内联.
#include <cassert>
#include <string>
#include <iostream>
struct A
{
// warning: ISO C++ forbids converting a string constant to ‘char*’
static constexpr char* name_ = "A";
static constexpr char* name() { return name_; };
};
int main()
{};
Run Code Online (Sandbox Code Playgroud)
如果我添加一个const后constexpr,警告消失了:
#include <cassert>
#include <string>
#include <iostream>
struct A
{
static constexpr const char* name_ = "A";
static constexpr const char* name() { return name_; }; …Run Code Online (Sandbox Code Playgroud)