标签: constexpr

constexpr函数是隐式静态的吗?

如果我在我的函数中定义一个函数program.cpp

constexpr bool isThree(const int number)
{
  return number == 3;
}
Run Code Online (Sandbox Code Playgroud)

与声明为静态有什么不同吗?

static constexpr bool isThree(const int number)
{
  return number == 3;
}
Run Code Online (Sandbox Code Playgroud)

似乎它们应该是等效的,因为这constexpr意味着函数是内联的,因此不能在编译单元之间共享。

constexpr全局函数隐含静态的?

c++ static-functions constexpr c++11

6
推荐指数
1
解决办法
343
查看次数

函数体中的 static constexpr 与 constexpr?

在函数体内使用static constexpr和时有什么区别吗?constexpr

int SomeClass::get(const bool b) 
{
    static constexpr int SOME_CONSTANT = 3;
    constexpr int SOME_OTHER_CONSTANT = 5;

    if(b)
        return SOME_CONSTANT;
    else
        return SOME_OTHER_CONSTANT;
}
Run Code Online (Sandbox Code Playgroud)

c++ static constexpr

6
推荐指数
1
解决办法
1539
查看次数

C++ - 将 constexpr char * 分配给 static char * 复制字符串...这是一个错误吗?

考虑以下程序。它只是将 a 复制constexpr const char *到 a static const char *。我希望指针被复制,并且是相同的。这就是 gcc、clang 和 msvc 的大多数选项都会发生的情况。

但是,当使用 flag/Zi标志而不是/ZI最近的 msvc 时,会触发断言。我想知道这是编译器错误还是只是未定义的行为。

#include <cassert>

constexpr const char *test = "test";

int main()
{
    static const char *a = test;
    assert(a == test);
}
Run Code Online (Sandbox Code Playgroud)

这是编译器资源管理器链接:https://godbolt.org/z/WPz7GPosa。只需在执行程序选项卡中更改/Zi为即可/ZI使断言消失。

谢谢!

c++ constexpr

6
推荐指数
0
解决办法
450
查看次数

为什么非 constexpr std::integral_constant 用作模板参数?

我的问题是为什么以下代码是有效的 C++:

#include <iostream>
#include <tuple>
#include <type_traits>

std::tuple<const char *, const char *> tuple("Hello", "world");

std::integral_constant<std::size_t, 0> zero;
std::integral_constant<std::size_t, 1> one;

template<typename T> const char *
lookup(T n)
{
  // I would expect to have to write this:
  //   return std::get<decltype(n)::value>(tuple);

  // But actually this works:
  return std::get<n>(tuple);
}

int
main()
{
  std::cout << lookup(zero) << " " << lookup(one) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

当然,我很高兴能够以这种方式编程。而且,我知道std::integral_constant有一个constexpr转换运算符。但是,参数ntolookup不是 constexpr,因此我对非 constexpr 对象上的非静态方法(即使方法本身是 constexpr)如何可能返回编译时常量感到困惑。

当然,在这种情况下我们碰巧知道转换运算符的主体不查看运行时值,但类型签名中没有任何内容保证这一点。例如,以下类型显然不起作用,尽管它也有 constexpr 转换运算符: …

c++ templates constexpr

6
推荐指数
1
解决办法
279
查看次数

在 constexpr 中传递参数包

我试图在编译时确定所有传递对象的大小,然后在超过最大大小时通过 static_assert 中止构建过程。

#include <iostream>

template<class T>
class Test
{
public:
    T value;
    constexpr size_t size() const { return sizeof(T) + 3; }
};

template<typename ...T>
constexpr int calc(const T&...args)
{
    return (args.size() + ...);
}

template<typename ...T>
void wrapper(const T& ...args)
{
    // error: 'args#0' is not a constant expression
    constexpr int v = calc(args...);
    static_assert(v <= 11, "oops"); 
}

int main()
{
    Test<int> a;
    Test<char> b;
    // a.size() + b.size() == 11

    // works
    constexpr int v = …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++17 parameter-pack

6
推荐指数
1
解决办法
163
查看次数

如何存储编译时动态分配的内存以便在运行时使用?

假设我有一个constexpr变量,其中包含所有小于 2 16的素数。

constexpr auto primes = [] {
    constexpr int N = 1 << 16;
    std::array<int, 6542> ret;
    bool not_prime[N] = {};
    int prime_cnt = 0;
    for (int i = 2; i < N; i++) {
        if (!not_prime[i]) {
            ret[prime_cnt++] = i;
            for (int j = 2 * i; j < N; j += i) not_prime[j] = true;
        }
    }
    return ret;
}();
Run Code Online (Sandbox Code Playgroud)

这里我手动指定了 的ret数组大小。当我想要更改时N,我必须重新运行此循环以查看最终prime_cnt值是什么并手动指定它。特别是,如果我增加N,我必须首先给出一个上限猜测以避免段错误。

在C++20中,我们可以在编译时动态分配内存,因此我们constexpr现在有了向量。所以我们不再需要担心上限问题。但这样的值不能在运行时使用,这意味着这段代码是无效的。 …

c++ constexpr c++20

6
推荐指数
1
解决办法
805
查看次数

constexpr 中允许未定义的行为——编译器错误?

我的理解是:

  • C++ 中的有符号整数溢出是未定义的行为
  • 常量表达式不允许包含未定义的行为。

看来像下面这样的东西不应该编译,事实上在我的编译器上它不编译。

template<int n> struct S { };

template<int a, int b>
S<a * b> f()
{
  return S<a * b>();
}

int main(int, char **)
{
  f<50000, 49999>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,现在我尝试以下方法:

#include <numeric>

template<int n> struct S { };

template<int a, int b>
S<std::lcm(a, b)> g()
{
  return S<std::lcm(a,b)>();
}

int main(int, char **)
{
  g<50000, 49999>();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

g++、clang 和 MSVC 都会愉快地编译它,尽管事实上

如果 |m|、|n| 或 |m| 的最小公倍数,则行为未定义 和|n| 不能表示为 type 的值 std::common_type_t<M, N> …

c++ undefined-behavior constexpr

6
推荐指数
1
解决办法
257
查看次数

一个 constexpr 函数,用于计算 std::vector 的嵌套深度

有没有办法编写一个 constexpr 函数来返回 std::vector 的嵌套深度?

例子:

get_vector_nested_layer_count<std::vector<std::vector<int>>>() // 2
get_vector_nested_layer_count<std::vector<std::vector<std::vector<float>>>>() // 3
Run Code Online (Sandbox Code Playgroud)

c++ templates constexpr constexpr-function

6
推荐指数
2
解决办法
386
查看次数

为什么成员函数不能要求同一类的 static constexpr 成员为 true?

我尝试让成员函数要求静态 constexpr 布尔成员为 true。这对于 DRY 一个相当复杂的需求非常有帮助。我不知道编译器不允许我这样做的原因。

要求稍微不那么复杂的最小示例:

template <typename T>
struct Foo
{
    static constexpr bool isInt = std::integral<T>;
    void bar() requires (isInt);
    void goo() requires std::integral<T>;
};

template <typename T>
void Foo<T>::bar() requires (Foo<T>::isInt) // error: out-of-line definition of 'bar' does not match any declaration in 'Foo<T>' x86-64 clang 14.0.0 #1
{
    // ...
}

template <typename T>
void Foo<T>::goo() requires std::integral<T> // ok
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

这是因为isInt是在同一个类中声明的吗?或者我有某种语法错误?

c++ constexpr c++20 requires-clause

6
推荐指数
1
解决办法
135
查看次数

为什么`constexpr向量`不允许在`consteval`函数中分配?

第四次编辑:原始问题标题是:

为什么constexpr说明符不允许非空std::vector

正如 @Barry 指出的,这个标题与C++20 constexpr vector and string not working重复。但我的问题描述有所不同:我constexpr vectorconstevalfunction而不是正常的运行时 function 或constexprfunction中分配。

据我所知,在编译时计算期间,只允许瞬时分配,正如 @Barry 在链接问题中回答的那样。

我感到困惑的是:对于consteval功能:

  1. 它的任何局部变量将在返回后被释放
  2. 它只在编译时返回,因为它只会在编译时被调用
  3. soconstexpr vector作为局部变量,将在编译时释放
  4. 那么为什么不允许呢?

我在下面的其他编辑回答了这个困惑。

-----------------以下是原问题描述----------

为什么下面的代码不能编译:

consteval int foo() {
  constexpr std::vector<int> vec{1};
  return vec[0];
}
Run Code Online (Sandbox Code Playgroud)

据我所知,只要分配和释放都发生在编译时,就可以在编译时使用 和std::vectorstd::string如果我删除constexpr说明符,该代码将编译。

但是添加constexpr仍然不违反这个规则,对吗?为什么不允许?

使用 gcc 13 编译时出现此错误,但我不明白:

/opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/bits/allocator.h:195:52: error:
'std::vector<int>(std::initializer_list<int>{((const int*)(& …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++20

6
推荐指数
0
解决办法
249
查看次数