触发联合非活动成员的左值到右值转换不是常量表达式。也就是说,给定union:
template<class T, class U>
union A {
constexpr A(T t) : t_{t} {}
constexpr A(U u) : u_{u} {}
T t_;
U u_;
};
Run Code Online (Sandbox Code Playgroud)
和constexpr功能foo:
template<class T, class U>
constexpr auto foo() {
A<T, U> a(T{});
return a.u_;
}
Run Code Online (Sandbox Code Playgroud)
以下程序:
int main() {
constexpr auto test = foo<int, double>();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
失败并显示错误消息:
error: constexpr variable 'test' must be initialized by a
constant expression
constexpr auto test = foo<int, double>();
^ ~~~~~~~~~~~~~~~~~~
note: …Run Code Online (Sandbox Code Playgroud) 我有一个变量,其地址作为第四个参数传递给setsocketopt。请注意,此参数被声明为常量指针 ( const void *optval)。
在我提交供审查的补丁中,我将该变量的声明更改为 static constexpr。此更改的审阅者对此表示担忧:他认为是否始终可以获取 constexpr 的地址是值得怀疑的。他建议我将其设为常量。在谷歌搜索后,我找不到太多关于 constexpr 变量地址的信息以及对此的担忧。有人可以解释一下与 constexpr 变量的地址有关的保证以及使用它的注意事项(如果有)吗?
如果它有帮助,这里是代码(我添加的static constexpr,这只是int之前的代码):
static constexpr int ONE = 1;
setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &ONE, sizeof(ONE));
Run Code Online (Sandbox Code Playgroud)
谢谢!
从 C++17 开始,std::array<T,N>::begin()是 constexpr:
constexpr iterator begin() noexcept;
Run Code Online (Sandbox Code Playgroud)
但是如何begin在编译时知道返回值呢?例如:
int main() {
auto p = std::make_unique<std::array<int,2>>();
auto it = p->begin();
}
Run Code Online (Sandbox Code Playgroud)
是完全合法的代码(虽然可能有点无用)。底层数组的开始以及迭代器取决于 malloc 的地址。
我有一种感觉,我对什么是误解,constexpr因为我看不到任何非静态成员函数可能是什么constexpr,特别是如果它(可传递地)访问数据成员。
constexpr int f() { return 0; }
int g() { return 0; }
constexpr auto c1 = f(); // OK
constinit auto c2 = f(); // OK
constexpr auto d1 = g(); // ill-formed
constinit auto d2 = g(); // ill-formed
int main() {}
Run Code Online (Sandbox Code Playgroud)
如上面的代码所示,我找不到constinit和之间的任何区别constexpr。
constinit和之间的真正区别是constexpr什么?
更新:
有关什么是constinit用C ++ 20?没有明确规定之间的差异constinit和constexpr。
我用 clang 和 gcc(主干版本)测试了以下代码。有人可以解释为什么使用普通 X 结构的情况不起作用,而按值捕获和使用 const 引用的包装情况都可以正常工作。
struct X {
constexpr X(const int &v) : x(v) {}
constexpr int Get() const { return x; }
private:
const int& x;
};
constexpr X f(const X& r) {
return r;
}
struct Y {
constexpr Y(const int &v) : x(v) {}
constexpr int Get() const { return x; }
private:
const int x;
};
constexpr Y f(const Y& r) {
return r;
}
struct Wrap {
constexpr Wrap(const int& v) : …Run Code Online (Sandbox Code Playgroud) 这个问题是基于这篇文章。
目标:我想知道一个类是否有成员变量x。我想收到true无论此变量是否为private,public或protected。
方法:如果类有成员变量,您可以使用以下代码获取信息:
template <typename T, typename = int>
struct HasX : std::false_type { };
template <typename T>
struct HasX <T, decltype((void) T::x, 0)> : std::true_type { };
Run Code Online (Sandbox Code Playgroud)
使用它
if constexpr (HasX<my_class>::value) {
// do stuff with x
} else {
// ...
}
Run Code Online (Sandbox Code Playgroud)
上面的代码在这种情况下不起作用
struct my_class {
private:
int x;
};
Run Code Online (Sandbox Code Playgroud)
我怎样才能使这项工作?我想HasX<my_class>::value是true。
想法:
使用friend可以访问T::x. 这似乎不起作用。看看这个活生生的例子。
我正在阅读C++17 - The Complete Guide 一书,在constexprlambda 的6.1 节中,作者给出了两个例子:
auto squared1 = [](auto val) constexpr { // example 1. compile-time lambda calls
return val * val;
};
Run Code Online (Sandbox Code Playgroud)
和
constexpr auto squared2 = [](auto val) { // example 2. compile-time initialization
return val * val;
};
Run Code Online (Sandbox Code Playgroud)
并说这两个彼此不同,因为示例 1在编译时评估,示例 2在编译时初始化。
然后作者做了以下我不完全理解的陈述:
如果(仅)lambda 是
constexpr它可以在编译时使用,但是如果由 lambda 初始化的(闭包)对象是constexpr,则该对象在程序启动时被初始化,但 lambda 可能仍然是一个只能在以下情况下使用的 lambda运行时(例如,使用静态变量)。因此,您可以考虑声明:Run Code Online (Sandbox Code Playgroud)constexpr auto squared = [](auto val) constexpr { // example 3 return val …
据我了解,关键字constexpr告诉编译器表达式的计算可以在编译时发生。具体来说,constexpr在变量上意味着可以在编译时评估变量的值,而constexpr在函数上意味着可以在编译时调用该函数并评估其返回值。如果函数在运行时被调用,它只是作为一个普通函数。
今天,我写了一段代码来尝试使用constexpr:
#include <iostream>
using namespace std;
constexpr long int fib(int n)
{
return (n <= 1)? n : fib(n-1) + fib(n-2);
}
int main ()
{
constexpr long int res = fib(32);
// const long int res = fib(32);
cout << res << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我原以为代码的编译会花费很多时间,但我错了。编译只用了0.0290s:
$ time g++ test.cpp
real 0m0.290s
user 0m0.252s
sys 0m0.035s
Run Code Online (Sandbox Code Playgroud)
但是如果我constexpr long int res = fib(32);换成const long int res = …
我想我明白为什么 C++ 不允许局部变量作为默认函数参数:
int main () {
auto local{1024};
auto lambda = [](auto arg1 = local){}; // "illegal use of local variable as default parameter"
}
Run Code Online (Sandbox Code Playgroud)
但即使该变量是constexpr local也是不允许的:
int main () {
constexpr auto local{1024};
auto lambda = [](auto arg1 = local){}; // "illegal use of local variable as default parameter"
}
Run Code Online (Sandbox Code Playgroud)
但是,允许使用全局变量(即使是非 constexpr):
int global;
int main () {
auto lambda = [](int arg1 = global){}; // OK
}
Run Code Online (Sandbox Code Playgroud)
有人可以解释在这种情况下不允许使用 constexpr 局部变量的理由吗?当默认值是固定的并且在编译时已知时,编译器似乎应该能够为函数构造适当的“默认参数”重载。
该CTRE库能够解析和使用类似语法在编译时验证的正则表达式ctre::match<"REGEX">(text_to_search)。我知道这种语法仅在 C++20 中受支持,这很好,但是无论我尝试什么,我都无法以这种方式使用字符串文字。这是一个非常简单的例子:
// The compiler refuses to pass string literals to STR in this compile time version.
template <char const STR[2]> constexpr int to_int_compile_time()
{
return STR[0] - '0';
}
// It has no problems passing the string literal to str in this version.
int to_int_runtime(char const str[2])
{
return str[0] - '0';
}
Run Code Online (Sandbox Code Playgroud)
调用to_int_runtime("0")工作正常,但to_int_compile_time<"0">()抱怨字符串文字不能用于此模板参数。应该如何to_int_compile_time编写才能将字符串文字传递到 char 数组模板参数中?