标签: constexpr

clang 上的 static constexpr 未定义引用错误

以下代码在 Visual Studio 2019 和 gcc 10.2(以及其他 gcc 版本)上可以正常编译,-std=c++11但在 clang(版本 9、10 和 11)上编译失败。

#include <map>
#include <string>

struct repo {
    static constexpr const char *x = "sth";
};

int main() {

    // 1) This compiles
    std::map<std::string, int> m1 = { {repo::x, 3} };
    
    // 2) This compiles
    std::map<std::string, std::string> m2 = { std::make_pair(repo::x, "") };
    
    // 3) This does not compile on clang
    std::map<std::string, std::string> m3 = { {repo::x, ""} };

    return 0;
}

Run Code Online (Sandbox Code Playgroud)

clang 的错误是:

... undefined …
Run Code Online (Sandbox Code Playgroud)

c++ clang constexpr

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

如何在嵌入式系统上创建指向寄存器的 constexpr 指针

我希望能够配置一个类,使其能够在其成员函数中访问硬件。假设我们有一个 avr 设备,我们可以简单地访问硬件,就像PORTA = 0x00;将 a 写入0x00io 内存空间一样。该问题对于每种嵌入式内存 io 访问都是通用的,而不是 avr 特有的。

但如果我现在想使用一个可以参数化的类,C++ 似乎已经关闭了所有的大门,因为似乎根本不可能定义任何类型的指针类型并给它们一个 constexpr 值。

在某些之前的编译器版本中,我们能够运行这样的代码:constexpr reference to avr port address

但现在所有尝试为 constexpr 值的指针赋值的尝试都会失败,因为reinterpret_cast在这种情况下不能再使用。

作为一个肮脏的黑客,我尝试过但失败了:

struct ONE 
{
    static constexpr volatile uint8_t* helper=nullptr;
    static constexpr volatile uint8_t* portc=&helper[100];
};
Run Code Online (Sandbox Code Playgroud)

失败并显示:

struct ONE 
{
    static constexpr volatile uint8_t* helper=nullptr;
    static constexpr volatile uint8_t* portc=&helper[100];
};
Run Code Online (Sandbox Code Playgroud)

也失败:

 // for AVR PORTB is defined in io.h like:
 #define PORTB (*(volatile uint8_t *)((0x05) + 0x20))

 constexpr …
Run Code Online (Sandbox Code Playgroud)

c++ pointers constexpr

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

为什么 std::vector::push_back 在 C++20 中声明为 constexpr?

根据cppref,在 C++20 中std::vector::push_back声明如下:

constexpr void push_back(const T& value);
Run Code Online (Sandbox Code Playgroud)

push_back我无法想象应该出现的场景constexpr

背后的原理是什么?

c++ stdvector constexpr c++20

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

gcc 如何在 constexpr 上下文中编译 C 函数?

鉴于C++ 标准库(当前)不提供 cmath 函数的 constexpr 版本,请考虑下面的程序。

#include <cmath>
#include <cstring>

int main()
{
    constexpr auto a = std::pow(2, 10);
    constexpr auto b = std::strlen("ABC");
}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,MSVC++ 和 clang++ 无法编译它,因为constexpr变量是从未声明的函数初始化的constexpr

然而,g++ 编译了这个。g++的版本似乎并不重要。

(在编译器资源管理器中查看全部)

g++ 是如何实现这一点的呢?这是正确的(允许的)编译器行为吗?

c++ gcc clang visual-c++ constexpr

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

constexpr 上下文中任何类内的 std::string 的 std::variant 无法编译

下面的代码

#include <optional>
#include <string>
#include <variant>

constexpr bool USE_VARIANT = 1;

using T = std::conditional_t<USE_VARIANT, std::variant<std::string>, std::string>;

struct S
{
    T t;
};

constexpr int func()
{
    S s{"str"};
    return 0;
}

constexpr int x = func();

int main()
{
}
Run Code Online (Sandbox Code Playgroud)

无法使用 GCC trunk(编译器资源管理器链接)进行编译,并显示以下消息

In file included from <source>:4:
<source>:21:23:   in 'constexpr' expansion of 'func()'
<source>:19:1:   in 'constexpr' expansion of '(& s)->S::~S()'
<source>:10:8:   in 'constexpr' expansion of '((S*)this)->S::t.std::variant<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::~variant()'
/opt/compiler-explorer/gcc-trunk-20211231/include/c++/12.0.0/variant:1408:28:   in 'constexpr' expansion of '((std::variant<std::__cxx11::basic_string<char, …
Run Code Online (Sandbox Code Playgroud)

c++ gcc constexpr c++20 std-variant

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

函数体中的 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
查看次数