标签: constexpr

编译器如何知道 C++ constexpr 计算不会触发未定义的行为?

C++ 标准要求编译器检查C++ constexpr 计算中未定义的行为

这次演讲中,Chandler Carruth 指出,在检查 UB 时“你将耗尽检测错误的能力”,并且在一般情况下,检测 UB 与停机问题有关,因此证明不可能做出决定

他不是在谈论 constexpr 中的 UB,但constexpr 计算与自 C++14 以来的常规程序一样通用,因此这仍然适用。

那么,当编译器无法确定程序是否是 UB 时,他们会做什么呢?他们是否仍然接受该程序并继续编译?或者他们是否更加保守并拒绝该计划,即使它可能是正确的?(我个人的感觉是他们这样做)

对我来说,这具有实际意义,因为我使用非平凡的指针算术进行了 constexpr 评估,用 Clang 编译得很好,但用 GCC 编译失败,而且我很确定这不是 UB。你可以说这是一个 GCC bug,但是如果 UB 是不可判定的,那么所有编译器在这方面都会存在 bug。

更根本的是,为什么标准要求不含 UB ?有技术原因吗?或者更多的是一种哲学(“如果编译器无法检查,程序员可以触发 UB,就会导致不好的结果”)?

我认为这与 C++ 的其余部分不一致,这永远不会阻止你搬起石头砸自己的脚。我希望 GCC 接受我的 constexpr 代码并崩溃,或者如果 UB 则发出垃圾;而不是在不知道是否是UB的情况下不编译。

====== 编辑======

正如 MM 和 Nicol Bolas 所指出的,该标准指定了限制(即使在 C++14 中也是如此),因此我们永远不会陷入 UB 的停止问题类型。然而,我仍然想知道检查 UB 是否可能太复杂,并且如果编译器启发式失败,那么它们会将其标记为非 constexpr(可能是错误的)。

但从评论中我感觉这更多是一个不成熟的实现问题。

c++ undefined-behavior language-lawyer constexpr

5
推荐指数
1
解决办法
312
查看次数

非常量 constexpr 成员函数的用例?

在 C++14 及更高版本中,constexprfor 成员函数不再意味着const

\n\n
struct Value\n{\n    int i = 5;\n\n    constexpr bool not_five() // requires const to compile\n    {\n        return this->i != 5;\n    }\n};\n\nint main()\n{\n    constexpr Value v{6};\n    static_assert(v.not_five());\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
error: passing \xe2\x80\x98const Value\xe2\x80\x99 as \xe2\x80\x98this\xe2\x80\x99 argument discards qualifiers [-fpermissive]\n  static_assert(v.not_five());\n                           ^\n
Run Code Online (Sandbox Code Playgroud)\n\n

似乎在编译时调用非常量 constexpr 成员函数意味着常量的突变,因为它所调用的对象在编译时存在并且正在发生突变。非常量 constexpr 成员函数的概念在什么情况下有用?

\n

c++ constants constexpr c++14

5
推荐指数
1
解决办法
166
查看次数

是否可以更改源文件内的 constexpr-ops-limit ?

我想换constexpr-ops-limit一个更大的数字。我知道可以作为-fconstexpr-ops-limit=命令行参数,但我无法更改参数,因为我将代码提交到自动运行它的系统。我想知道 GCC 或 VC++ 中是否有任何编译指示可以满足我的需求。

有什么办法可以做到吗?先感谢您。

c++ pragma constexpr c++14 c++17

5
推荐指数
0
解决办法
664
查看次数

MSVC constexpr 编译器错误?

环境:VS 2019,v16.4.3 w/c++17 + 最新开关

以下代码标准是否正确,还是我做错了什么?它使用最新的 gcc/clang 编译器可以正常编译,但在 MSVC 上失败。(请参阅下面的错误消息)

template<typename T>
struct mixin {};

struct thing : mixin<thing>
{
    constexpr explicit thing(int value) : value_(value) {}

    constexpr int value() const { return value_; }

private:
    int value_ = 0;
};

template<typename T>
constexpr auto do_mixin_thing(mixin<T> const& m)
{
    return static_cast<T const&>(m).value() * 10;
}

int main()
{
    constexpr thing t1{ 10 };

    // this works
    static_assert(t1.value() == 10);

    // this fails
    static_assert(do_mixin_thing(t1) == 100);
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

error C2131: expression …
Run Code Online (Sandbox Code Playgroud)

c++ visual-c++ constexpr c++17

5
推荐指数
1
解决办法
382
查看次数

扔进 constexpr 函数:我们需要包装条件吗?

基本思想是这样的:我有一些constexpr函数,我想用它throw来发出错误信号和延迟编译以避免正常流程中出现此错误:

template <size_t N>
auto constexpr find_elt(const std::array<int, N>& a, int k) {
  for (size_t i = 0; i < N; ++i)
    if (k == a[i])
      return i;
  throw "not found";
}
Run Code Online (Sandbox Code Playgroud)

进而:

constexpr int result = find_elt(arr, 4);
Run Code Online (Sandbox Code Playgroud)

通常,如果数组中存在 4,我将在编译时获取其索引。

如果没有,我就会陷入困境throw编译时的查找是错误的,并且编译器将产生一个漂亮的错误。

但我注意到奇怪的行为:

在最新的 clang 下,一切正常

在最新的gcc下,一切都失败了

这个想法合法吗?这段代码对于我想要实现的目标是否正确?哪个编译器在这里告诉我真相?

如果不是,正确的方法是什么?

任何到 C++ 标准的链接都值得赞赏。我通读了 constexpr 相关的章节,但我有疑问。

c++ constexpr c++17

5
推荐指数
1
解决办法
749
查看次数

constexpr(sizeof(T)): 为什么在 `sizeof` 上指定 `constexpr`?

今天有人请我帮忙做一个用 G++ 编译的 VC++ 项目,我偶然发现了这一行:

static char data[constexpr(sizeof(T))];
Run Code Online (Sandbox Code Playgroud)

(当然,它位于带有名为 的模板参数的模板函数内T)。

我没有 C++ 标准,但根据cppreference

句法

sizeof( 类型 ) (1)

表达式的大小 (2)

两个版本都是 std::size_t 类型的常量表达式。

sizeof()那么告诉 VC++预期的结果有什么意义呢constexpr


尝试一下: https: //rextester.com/VIWP36674

正如预期的那样,在 VC 上有效,但在 G++ 上失败。

另一种尝试选择: https: //godbolt.org/z/DnioLS

适用于 VC 直至 19.10。似乎是在 19.14 修复的,所以我认为这确实是一个怪癖,但即使如此,也一定有人有理由编写这样的代码......

c++ g++ sizeof visual-c++ constexpr

5
推荐指数
1
解决办法
1133
查看次数

constexpr for 循环编译

我已经读过这篇文章,但我仍然不知道如何使其工作,-std=gnu++2a 我不知道如何使用integer seq。您能帮我修改下面的代码以便它可以编译吗?谢谢

constexpr bool example(const int k)
{
    return k < 23 ? true: false;
}

constexpr bool looper()
{
    constexpr bool result = false;
    for(int k = 0; k < 20; k ++)
    {
        for (int i = 0 ; i < k; ++i)
        {
        constexpr bool result = example(i);
        }
    }

    return result;
}

int main()
{
    constexpr bool result = looper();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c++ metaprogramming constexpr c++11 c++17

5
推荐指数
1
解决办法
3398
查看次数

使用 SFINAE 检查函数是否为 constexpr

我想检查一个函数是否可以在编译期间被评估。我发现了这个,但我不完全理解这个概念。我有几个疑问:

  1. 代码中下面这行的作用是什么?
    template<int Value = Trait::f()>

  2. 每次当我需要检查该函数是否可以在编译时评估时,是否需要将其设为某个结构的成员函数?

PS
我复制链接中的代码,只是为了方便。

template<typename Trait>
struct test
{
    template<int Value = Trait::f()>
    static std::true_type do_call(int){ return std::true_type(); }

    static std::false_type do_call(...){ return std::false_type(); }

    static bool call(){ return do_call(0); }
};

struct trait
{
    static int f(){ return 15; }
};

struct ctrait
{
    static constexpr int f(){ return 20; }
};

int main()
{
   std::cout << "regular: " << test<trait>::call() << std::endl;
   std::cout << "constexpr: " << test<ctrait>::call() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

c++ templates compile-time sfinae constexpr

5
推荐指数
1
解决办法
202
查看次数

constexpr 构造函数的参数类型 'std::function' 不是文字类型

我正在编写一个简单的 C++ HTTP 服务器框架。在我的Server课堂上,我可以添加Route's。每个路由都包含一个路径、一个 HTTP 方法和一个Controller(这是发出请求时要调用的函数的管道。)该类Controller是通过接收 的列表std::function(或者更准确地说std::function<void(const HTTPRequest&, HTTPResponse&, Context&)>:)来构造的,但大多数有时(或者我应该说每次),这Controller将使用 lambda 函数文本列表进行初始化,如以下代码所示:

server.add_route("/", HTTPMethod::GET,
                {
                    [](auto, auto& response, auto&) {
                        const int ok  = 200;
                        response.set_status(ok);
                        response << "[{ \"test1\": \"1\" },";
                        response["Content-Type"] = "text/json; charset=utf-8";
                    },
                    [](auto, auto& response, auto&) {
                        response << "{ \"test2\": \"2\" }]";
                    },
                }
        );
Run Code Online (Sandbox Code Playgroud)

既然如此,我想将add_route函数设为 a constexpr,因为如果我错了,请纠正我,constexpr函数可以在编译时执行。

所以,当我做一切的时候constexpr,我发现了以下错误:

Controller.cpp:9:1 constexpr …
Run Code Online (Sandbox Code Playgroud)

c++ lambda constexpr c++11 constexpr-function

5
推荐指数
1
解决办法
930
查看次数

为什么这个 std::string_view 不是常量表达式?

我对constexpr编程比较陌生,正在尝试string_viewconstexpr上下文中对对象进行一些基本操作。就我而言,所有字符串在我的源代码中都以文字开头,因此它们似乎应该是常量表达式。我发现我可以constexpr string_view从字符串文字构造 a ,没有任何问题。

但是,如果我尝试调用一个采用字符串文字作为参数的constexpr函数,则编译会失败。string_view请参阅以下示例(编译器资源管理器链接):

#include <string_view>

// this doesn't compile; the compiler complains that `sv` is not a constant-expression
constexpr bool foo(std::string_view sv) 
{
    constexpr auto it = sv.find('b'); 
    return it != sv.end();
}

// this compiles just fine, though
constexpr std::string_view bar("def");

int main()
{
    foo("abc");
}
Run Code Online (Sandbox Code Playgroud)

gcc 8.3 提供以下错误:

<source>: In function 'constexpr bool foo(std::string_view)':
<source>:5:32:   in 'constexpr' expansion of 'sv.std::basic_string_view<char>::find(((int)'b'), 0)'
<source>:5:36: …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++17

5
推荐指数
1
解决办法
2163
查看次数