constexpr if 和 return 值优化
constexpr if and the return value optimization
我有这个代码:
#include <string>
class A {
public:
// A(A const &) = delete; // Code fails if this is uncommented.
explicit A(int);
explicit A(::std::string const &);
private:
::std::string myname_;
int foo_;
};
static constexpr bool which = false;
A test(::std::string const &s, int a)
{
if constexpr (which) {
A x{a};
return x;
} else {
A y{s};
return y;
}
}
如果 A
具有已删除的复制构造函数,则此代码将失败。但是,考虑到关于 return 类型的规则,其中包含 if constexpr
的函数,似乎编译器应该在这里应用 RVO。
除了语言规范中被忽视的情况外,还有其他原因吗?
这与if constexpr
无关
只是这段代码不允许编译:
class A {
public:
A(A const &) = delete;
explicit A(int);
};
A test(int a)
{
A x{a};
return x; // <-- error call to a deleted constructor `A(A const &) = delete;`
}
您正在考虑的 C++17 中的更改与 temporary materialization 有关并且不适用于 NRVO,因为 x
不是纯右值。
例如,此代码在 C++17 之前是非法的,现在允许使用:
A test(int a)
{
return A{a}; // legal since C++17
}
这是NRVO,这是非强制复制省略:
(强调我的)
- In a return statement, when the operand is the name of a non-volatile object with automatic storage duration, which isn't a
function parameter or a catch clause parameter, and which is of the
same class type (ignoring cv-qualification) as the function return
type. This variant of copy elision is known as NRVO, "named return
value optimization".
This is an optimization: even when it takes place and the copy/move
(since C++11)
constructor is not called, it still must be present and
accessible (as if no optimization happened at all), otherwise the
program is ill-formed:
顺便说一句:请注意,在您的代码中,将检查 constexpr if 语句的 if
部分和 else
部分。
Outside a template, a discarded statement is fully checked. if
constexpr is not a substitute for the #if preprocessing directive:
void f() {
if constexpr(false) {
int i = 0;
int *p = i; // Error even though in discarded statement
}
}
我有这个代码:
#include <string>
class A {
public:
// A(A const &) = delete; // Code fails if this is uncommented.
explicit A(int);
explicit A(::std::string const &);
private:
::std::string myname_;
int foo_;
};
static constexpr bool which = false;
A test(::std::string const &s, int a)
{
if constexpr (which) {
A x{a};
return x;
} else {
A y{s};
return y;
}
}
如果 A
具有已删除的复制构造函数,则此代码将失败。但是,考虑到关于 return 类型的规则,其中包含 if constexpr
的函数,似乎编译器应该在这里应用 RVO。
除了语言规范中被忽视的情况外,还有其他原因吗?
这与if constexpr
只是这段代码不允许编译:
class A {
public:
A(A const &) = delete;
explicit A(int);
};
A test(int a)
{
A x{a};
return x; // <-- error call to a deleted constructor `A(A const &) = delete;`
}
您正在考虑的 C++17 中的更改与 temporary materialization 有关并且不适用于 NRVO,因为 x
不是纯右值。
例如,此代码在 C++17 之前是非法的,现在允许使用:
A test(int a)
{
return A{a}; // legal since C++17
}
这是NRVO,这是非强制复制省略:
(强调我的)
- In a return statement, when the operand is the name of a non-volatile object with automatic storage duration, which isn't a function parameter or a catch clause parameter, and which is of the same class type (ignoring cv-qualification) as the function return type. This variant of copy elision is known as NRVO, "named return value optimization".
This is an optimization: even when it takes place and the copy/
move (since C++11)
constructor is not called, it still must be present and accessible (as if no optimization happened at all), otherwise the program is ill-formed:
顺便说一句:请注意,在您的代码中,将检查 constexpr if 语句的 if
部分和 else
部分。
Outside a template, a discarded statement is fully checked. if constexpr is not a substitute for the #if preprocessing directive:
void f() { if constexpr(false) { int i = 0; int *p = i; // Error even though in discarded statement } }