标签: constexpr

constexpr:gcc 比 clang 更努力地评估 constexpr

我正在使用 Godbolt 来查看带有 gcc 和 clang 的生成代码。

我试图实现djb2 hash

gcc 总是试图最好地评估 constexpr 函数。

只有当变量是 constexpr 时,clang 才会评估 constexpr。

让我们看看这个例子:

constexpr int djb2(char const *str)
{
    int hash = 5381;
    int c = 0;

    while ((c = *str++))
    hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
        return hash;
}

int main()
{
    int i = djb2("hello you :)");
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,gcc 正在评估一个编译时间 i。但是在运行时叮当响。

如果我将 constexpr 添加到i,clang 也在编译时进行评估。

您知道标准是否对此有所说明吗?

编辑:谢谢大家。所以,据我所知,没有 constexpr …

c++ gcc clang constexpr c++17

0
推荐指数
1
解决办法
215
查看次数

constexpr 函数采用 const char*

我使用 MSVC v141 和/std:c++17.

constexpr const char* test(const char* foo) {
    return foo + 1;
}

constexpr const char* bc = test("abc");
Run Code Online (Sandbox Code Playgroud)

编译得很好,而

constexpr const char* test(const char* foo) {
    constexpr auto bar = foo;
    return bar + 1;
}

constexpr const char* bc = test("abc");
Run Code Online (Sandbox Code Playgroud)

失败:

错误 C2131:表达式未计算为常量

失败是由在其生命周期之外读取变量引起的

注意:参见'foo'的用法

这是正确的行为还是 MSVC 中的错误?

c++ constexpr

0
推荐指数
1
解决办法
86
查看次数

编译时评估代码中的重言式是否保证被执行/优化掉?

编译器是否保证评估环境constexpr"tautologies"(例如始终truefalse分别)的布尔表达式constexpr

最小示例/说明

例如,在以下代码片段(在标有 的行(1))中,我在constexpr环境中调用了一个函数,我打算在non-constexpr传递函数时导致编译时错误。至少我使用的编译器 ( g++-10.0) 是这样做的,即使它也可以意识到表达式总是true不计算它。我问这个问题的原因是 - 据我所知 - 在非 constepxr 上下文中,像这样的表达式i >= std::numeric_limits<int>::min()被优化trueint i.

#include <limits>
constexpr int example_function() { return 1;}
constexpr bool compileTimeErrorDesired = example_function() || true; // (1)
Run Code Online (Sandbox Code Playgroud)

应用实例

如果(1) 保证in 的行为,则可以在 aconcept中使用它,以执行不同的代码,具体取决于是否可以在编译时评估作为模板参数提供的函数。我实现了一个非常短的 ( 7 lines-of-code) 示例,它在编译器资源管理器中完全做到这一点。

如果使用非 constexpr 函数调用,行 (1) …

c++ language-lawyer constexpr c++-concepts c++20

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

使用现代 C++ 技术确定整数是奇数还是偶数的最有效方法

我写了这个简单的辅助constexpr函数:

#include <cstdint>

constexpr bool isEven(uint32_t value) { return ((value%2) == 0); }
Run Code Online (Sandbox Code Playgroud)

这非常简单。我想知道这是否被认为是确定某个整数值是奇数还是偶数的最有效方法?目前我并不担心为不同的积分类型模板化这个函数。我只是在追求效率和性能,同时牢记便携性。

编辑

为了提供一些上下文,我可能会在一个循环中调用这个函数,该循环可以迭代 100,000 次到 100,000,000 次或更多...所以效率是这里的关键,但可移植性仍然是一个因素...

正如其他人在评论或答案中所述,我曾通过检查最低有效位来考虑“按位运算”,但是,我不确定编译器是否会在这种情况下优化模运算符。

关于可移植性,我不确定“字节序”或“整体约定”是否是应该使用实现的主要因素。考虑一个仅实现 1 的补码而不是 2 的补码的系统,或者使用 Big Endian 而不是 Little 的系统,可能需要加以考虑。

c++ performance constexpr c++17

0
推荐指数
1
解决办法
1040
查看次数

为什么会编译“if constexpr”的错误分支?

为什么这段代码在编译时出错?我对“ ”的了解(以及这个if constexpr表明该else块不应该被编译。

if constexpr (true) {
    int a = 10;
} else {
    int b = 10
}
Run Code Online (Sandbox Code Playgroud)

错误是:

error: expected ‘,’ or ‘;’ before ‘}’ token
Run Code Online (Sandbox Code Playgroud)

使用的编译器:g++ version 7.5.0
编译时我使用了-std=c++17标志。

PS缺少的';' 是故意的,只是为了检查是否else正在编译。

c++ constexpr c++17 if-constexpr

0
推荐指数
1
解决办法
232
查看次数

非编译时计算函数 constexpr 如何?

为什么非编译时计算函数“产品”可以是constexpr

#include <iostream>

constexpr int product(int x, int y) {
    return x * y;
}

int main(int argc, char* argv[]) {
    using namespace std;
    int x1, y1 = 0;
    cout << "input x1:\n";
    cin >> x1;
    cout << "input y1:\n";
    cin >> y1;
    const int a = product(x1, y1);
    cout << a << endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c++ constexpr

0
推荐指数
1
解决办法
57
查看次数

使用 constinit const 时 static_assert 失败。constinit、constinit const、constexpr、const、非常量变量中的混淆

我有一个关于编译时函数的问题。我知道 static_assert 应该只适用于可以在编译时评估/计算的类型。所以它不适用于 std::string (然而,gcc10 中不支持 constexpr std::string)但可以使用 std::array(当我在编译时知道大小时)。我正在观看 Jason Turner 的 C++ Weekly,所以这个片段来自这一集https://www.youtube.com/watch?v=INn3xa4pMfg

代码在这里:https : //godbolt.org/z/e3WPTP

#include <array>
#include <algorithm>

template<typename Key, typename Value, std::size_t Size>
struct Map final
{
    std::array<std::pair<Key, Value>, Size> _data;

    [[nodiscard]] constexpr Value getMappedKey(const Key& aKey) const
    {
        const auto mapIterator = std::ranges::find_if(_data, [&aKey](const auto& pair){ return pair.first == aKey;});

        if(mapIterator != _data.end())
        {
            return mapIterator->second;
        }
        else
        {
            throw std::out_of_range("Key is not in the map");
        }
    }
};

enum class OurEnum …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++20 constinit

0
推荐指数
1
解决办法
153
查看次数

为什么即使在使用 constexr if 时也会“使用未声明的标识符”?

玩代码。

template<typename T>
T f() {
    if constexpr (std::is_same<T, int>::value) {
        T t = 10;
    }else {
        T t;
    }
    return t;
}
Run Code Online (Sandbox Code Playgroud)

我对上述代码的理解f

int t = 10; 
return t;
Run Code Online (Sandbox Code Playgroud)

或者

T t = // some default value for T 
return t;
Run Code Online (Sandbox Code Playgroud)

取决于T. 在两者中都会有一个名为 的标识符t。为什么编译器仍然抱怨use of undeclared identifier 't'?。

编译器在解析constexpr语句之前是否检查未声明的标识符?

c++ if-statement undeclared-identifier constexpr

0
推荐指数
1
解决办法
172
查看次数

变量上的 consteval 与 constexpr

有什么区别constexprconsteval

 consteval int x1 = 2;
 constexpr int x2 = 5;
Run Code Online (Sandbox Code Playgroud)

使用 constexpr 比使用 consteval 更好吗?

c++ constexpr c++11 c++20 consteval

0
推荐指数
1
解决办法
518
查看次数

为什么`auto` 不采用其初始化表达式的constexpr'ness?

为什么用auto关键字定义变量不带有constexpr用于初始化它的表达式的“性质”?


例如,请考虑以下代码:

#include <string_view>

constexpr std::string_view f() { return "hello"; }

static constexpr std::string_view g() {
    constexpr auto x = f(); // (*)
    return x.substr(1, 3);
}

int foo() { return g().length(); }
Run Code Online (Sandbox Code Playgroud)

使用 GCC 10.2 和--std=c++20 -fsanitize=undefined -O3编译为:

foo():
        mov     eax, 3
        ret
Run Code Online (Sandbox Code Playgroud)

但是,如果我们删除 (*) 行上的 constexpr,我们将得到一个 27 行的程序,其中包含一堆指针、一个长字符串常量等。

笔记:

  • 我将此问题标记为 C++20,但我没有理由相信这种行为与 C++11 不同。
  • 这个问题与示例无关,而是关于autowrt constexprness的一般行为。该示例只是表明 GCC 不会将 x 视为constexpr我们没有明确告诉它。

c++ type-inference constexpr auto c++20

0
推荐指数
1
解决办法
134
查看次数