标签: constexpr-function

为什么可以在函数内的常量表达式中使用作为 constexpr 函数参数的参数传递的 lambda 的返回值?

问题标题的措辞可能不正确,我会很乐意根据您的建议进行修复。

我的问题可以用这个片段来说明:

#include <array>

template <typename Callable>
constexpr auto make_array_ok(Callable callable) {
    return std::array<int, callable()>{};
};
// constexpr auto make_array_bad(std::size_t s)
// {
//     return std::array<int,s>{};
// };

int main(int argc, char**) {
    static_cast<void>(argc);

    auto size = []() { return std::size_t{42}; };

    // fails to compile -- as I expected
    // auto size_dyn = [argc]() { return std::size_t(argc); };
    // auto a = make_array_ok(size_dyn);

    // also fails to compile -- but why?
    // auto size_capt = [arg = size()]()constexpr{return arg;}; …
Run Code Online (Sandbox Code Playgroud)

c++ constant-expression callable-object constexpr-function

9
推荐指数
2
解决办法
678
查看次数

非 constexpr 调用的 constexpr 结果

最近,我很惊讶以下代码也在 clang、gcc 和 msvc 中编译(至少在它们当前的版本中)。

struct A {
    static const int value = 42;
};

constexpr int f(A a) { return a.value; }

void g() {
    A a;  // Intentionally non-constexpr.
    constexpr int kInt = f(a);
}
Run Code Online (Sandbox Code Playgroud)

我的理解是,调用f不是 constexpr 因为参数i不是,但看来我错了。这是适当的标准支持的代码还是某种编译器扩展?

c++ constexpr c++11 constexpr-function

8
推荐指数
1
解决办法
761
查看次数

鉴于 C++23 对 constexpr 的放宽,constexpr 不能成为默认值吗?

关键字constexpr在引入 C++11 标准时对其函数实施了相当严格的限制。C++14 和 C++20 放宽了这些限制(最值得注意):

  • C++14 允许多个return语句static_assert等。
  • C++20 允许try并且asm

C++23 进一步软化了这些限制。从我在cppreference中看到的,constexprfor函数似乎只剩下以下含义:

  • 它不能是协程
  • 对于构造函数和析构函数,该类必须没有虚拟基类
  • 对于 constexpr 函数模板和类模板的 constexpr 成员函数,至少一种特化必须满足上述要求。

C++23 甚至删除了 constexpr 函数必须在编译时对于p2448r2中的任何类型“可计算”的限制。根据我的理解,这完全消除了constexpr在编译时评估函数的想法。

是这样吗?如果是这样,constexpr函数还有什么用处呢?

c++ language-design constexpr constexpr-function c++23

8
推荐指数
1
解决办法
1100
查看次数

一个 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
查看次数

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
查看次数

constexpr 函数仅在声明为看似无关的模板时才有效

以下代码无法编译;g++ 7.3.0 with--std=c++17给出了错误信息

constexpr 函数 'constexpr const C operator+(const C&, int)' 的无效返回类型 'const C'
注意:'C' 不是文字,因为 'C' 有一个非平凡的析构函数

#include <string>

using namespace std ;

struct C
  {
  C (std::string s) : s (s) { }
  std::string s ;
  } ;

constexpr const C operator+ (const C& x, int y) // <-- Error here
  {
  return C ("C int") ;
  }

int main()
  {
  C c ("abc") ;
  printf ("%s\n", (c + 99).s.c_str()) ;
  }
Run Code Online (Sandbox Code Playgroud)

好吧,好吧。但是如果我添加一个看似无关的模板规范到operator+

template<typename …
Run Code Online (Sandbox Code Playgroud)

c++ function-templates c++17 constexpr-function

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

“constexpr”函数中对“文字类型”的要求

这是我的代码:

class agg_t1{
    int x;      // private non-static data menber
};
class agg_t2{
    agg_t2(){}      // user-provided constructor
};
constexpr void ce1(agg_t1 arg){};       // OK
constexpr void ce2(agg_t2 arg){};       // ERROR:  parameter type 'agg_t2' is not a literal type 
Run Code Online (Sandbox Code Playgroud)

根据dcl.constexpr

constexpr 函数的定义应满足以下要求: ...

  • 它的每个参数类型都应该是文字类型;...

basic#types.general-10

如果类型是文字类型,则它是: ...

  • 它可以是闭包类型、聚合类型,或者......

我理解为什么agg_t2不是文字类型的原因是,它违反了规则dcl.init.aggr#1.1

聚合是一个数组或一个类......

  • 没有用户声明或继承的构造函数...

我认为agg_t1可能不是文字类型,因为它也违反了规则dcl.init.aggr#1.1

聚合是一个数组或一个类......

  • 没有私有或受保护的直接非静态数据成员...

然而......编译器结果告诉我我对 的假设是错误的agg_t1

我的问题是:

如果agg_t1的私有数据成员x …

c++ language-lawyer constant-expression constexpr constexpr-function

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

“constexpr”函数不应声明为“内联”

通过使用SonarLint分析代码,我收到了一条关于析构函数的消息(问题的标题),其声明如下:

class Foo
{
public:
.   // default ctor
.   // parameterized ctor
.
    inline ~Foo() = default; // dtor
.
.   // copy ctor = delete
.   // copy assignment operator = delete
.   // move ctor
.   // move assignment operator

private:
    ...
    mutable std::vector< std::vector<char> > m_Matrix;
    ...
};
Run Code Online (Sandbox Code Playgroud)

以下是消息的描述声明函数或静态成员变量 constexpr 使其隐式内联。

我不认为此类的 dtor 可以是constexprorconsteval因为它具有类型的非静态数据成员std::vector,因此~Foo必须delete[]在某个时刻调用以释放向量的存储。

那么为什么SonarLint显示此消息呢?是因为吗 = default?是否有任何 …

c++ destructor inline-functions sonarlint constexpr-function

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

C++20 是否可以让 constexpr 函数返回具有静态 constexpr 数组且值通过宏传递的类型的元组?

经过两三天的尝试,我不得不放弃并编写了一个“最小”测试用例,希望能够证明该问题。

我需要的是一种将字符串文字(作为不带引号的宏参数传递)转换为可在 constexpr 环境中访问的字符串(用前缀连接)的方法(请参阅https://wandbox.org/permlink/Cr6j6fXemsQRycHI真实代码( tm));这意味着,它们(宏参数)应该被字符串化,然后转换为类型(例如 template <... 'h', 'e', 'l', 'l', 'o', ...>)或转换为static constexpr array<char, N>传递的唯一类型的 a (例如 template <... A<1> ...>,其中A<1>::strastatic constexpr array<char, 6>包含内容'h', 'e', 'l', 'l', 'o', '\0'.

我强烈喜欢后者,只有当后者不可能时才选择前者。

为了在简短的测试用例中演示确切的问题/要求,我提出了以下内容:

一些标题...

#include <array>
#include <tuple>
#include <cassert>
#include <string>
#include <iostream>
Run Code Online (Sandbox Code Playgroud)

然后为了演示最终结果应该如何表现:

template<int I>
struct A;

template<>
struct A<0>
{
  static constexpr auto str = std::to_array("abc"); // The string-literal "abc" may NOT appear here.
                                                    // …
Run Code Online (Sandbox Code Playgroud)

c++ constexpr c++20 constexpr-function

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

编译器无法执行 constexpr 表达式

我有这样的代码:

template<typename ... Args>
constexpr size_t get_init_size(Args ... args) {
    return sizeof...(Args);
}

template<typename ... Args>
constexpr auto make_generic_header(Args ... args) {
    constexpr size_t header_lenght = get_init_size(args...);
    return header_lenght;
}

constexpr auto create_ipv4_header() {
    constexpr auto x = make_generic_header(0b01, 0b10, 0b01);
    return x;
}
Run Code Online (Sandbox Code Playgroud)

我知道这是虚拟代码,但我将其隔离以查找错误。

编译器给我错误(GCC):

In instantiation of 'constexpr auto make_generic_header(Args&& ...) [with Args = {int, int, int}]':
/tmp/tmp.CaO5YHcqd8/network.h:39:43:   required from here
/tmp/tmp.CaO5YHcqd8/network.h:31:22: error: 'args#0' is not a constant expression
   31 |     constexpr size_t header_lenght = get_init_size(args...);
      |                      ^~~~~~~~~~~~~ …
Run Code Online (Sandbox Code Playgroud)

c++ templates constexpr c++17 constexpr-function

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