标签: constexpr

宽松常量表达式中联合非活动成员的左值到右值转换的解决方法

触发联合非活动成员的左值到右值转换不是常量表达式。也就是说,给定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)

c++ unions constexpr c++14

4
推荐指数
1
解决办法
403
查看次数

可以使用 constexpr 变量的地址吗?

我有一个变量,其地址作为第四个参数传递给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++ pointers memory-address constexpr c++11

4
推荐指数
1
解决办法
875
查看次数

为什么 std::array&lt;T,N&gt;::begin() 自 C++17 以来是 constexpr?

从 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,特别是如果它(可传递地)访问数据成员。

c++ compile-time constexpr c++17

4
推荐指数
1
解决办法
271
查看次数

“constinit”和“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?没有明确规定之间的差异constinitconstexpr

c++ constexpr semantics c++20 constinit

4
推荐指数
1
解决办法
149
查看次数

constexpr 与 const 引用交互的奇怪行为

我用 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)

c++ constexpr c++20

4
推荐指数
1
解决办法
70
查看次数

如何检测类中是否存在特定的PRIVATE成员变量?

这个问题是基于这篇文章

目标:我想知道一个类是否有成员变量x。我想收到true无论此变量是否为privatepublicprotected

方法:如果类有成员变量,您可以使用以下代码获取信息:


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>::valuetrue

想法:

使用friend可以访问T::x. 这似乎不起作用。看看这个活生生的例子

c++ friend template-meta-programming constexpr

4
推荐指数
1
解决办法
129
查看次数

constexpr 与 lambda 表达式的 C++ 用法

我正在阅读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运行时(例如,使用静态变量)。因此,您可以考虑声明:

constexpr auto squared = [](auto val) constexpr { // example 3
  return val …
Run Code Online (Sandbox Code Playgroud)

c++ lambda constexpr c++17

4
推荐指数
1
解决办法
132
查看次数

为什么在运行时而不是在编译时使用 constexpr 初始化变量

据我了解,关键字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++ compilation constants constexpr c++11

4
推荐指数
1
解决办法
148
查看次数

为什么不允许 constexpr 局部变量作为默认函数参数?

我想我明白为什么 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 局部变量的理由吗?当默认值是固定的并且在编译时已知时,编译器似乎应该能够为函数构造适当的“默认参数”重载。

c++ default-arguments constexpr

4
推荐指数
1
解决办法
69
查看次数

将字符串文字传递给模板字符数组参数

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 数组模板参数中?

c++ string-literals compile-time constexpr c++20

4
推荐指数
1
解决办法
69
查看次数