如何解决constexpr构造函数的参数类型'std :: function'不是文字类型 编辑constexpr行为示例
我正在编写一个简单的C ++ HTTP服务器框架。在我的Server
类中,可以添加Route
。每个路由都包含一个路径,一个HTTP方法和一个Controller
(这是在发出请求时要调用的函数的管道。)Controller
类是通过接收{{ 1}}(或更精确地说:std::function
),但是在大多数情况下(或者我应该说每次时间),此std::function<void(const HTTPRequest&,HTTPResponse&,Context&)>
会使用lambda函数文字列表,如以下代码所示:
Controller
在这种情况下,我想将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 << "{ \"test2\": \"2\" }]";
},}
);
函数设为add_route
,因为如果我错了,请纠正我,constexpr
函数可以在编译时执行。 / p>
因此,当我做所有constexpr
时,发现以下错误:
constexpr
我想知道的是:为什么Controller.cpp:9:1 constexpr constructor's 1st parameter type 'Callable' (aka 'function<void (const HTTPRequest &,HTTPResponse &,Context &)>') is not a literal type
不能是文字类型?有什么办法可以规避这一限制?
下面是std::function
类的代码。我知道仍然存在其他编译错误,但这是我现在要解决的主要问题。预先感谢!
Controller
controller.hpp
#pragma once
#include <functional>
#include <initializer_list>
#include <vector>
#include "context.hpp"
#include "httprequest.hpp"
#include "httpresponse.hpp"
typedef std::function<void(const HTTPRequest&,Context&)> Callable;
template <size_t N>
class Controller {
private:
std::array<Callable,N> callables;
public:
static auto empty_controller() -> Controller<1>;
constexpr explicit Controller(Callable);
constexpr Controller();
constexpr Controller(std::initializer_list<Callable>);
void call(const HTTPRequest&,Context&);
};
controller.cpp
解决方法
为什么std :: function不能是文字类型?有什么办法可以规避这一限制?
因为它使用类型擦除来接受任何可调用对象。这需要在C ++ 20允许constexpr virtual
之前不能是constexpr的多态性。
您可以使用模板并直接捕获可调用对象,但是其类型将蔓延到Controller
中并进一步传播。
在这种情况下,我想使add_route函数成为constexpr,因为如果我错了,请更正我,可以在编译时执行constexpr函数。
是,如果给定 constexpr
参数,则该函数将在编译时执行。像高级连续折叠一样看它。此外,在编译时上下文中使用的constexpr
方法不能访问*this
或也必须是constexpr。特别是,constexpr
方法只能在编译时更改constexpr
实例的状态。否则,该函数通常在运行时运行。
最后一点与您有关,在编译时运行HTTP服务器几乎没有任何意义,因此constexpr
可能不需要,也无济于事。
编辑constexpr
行为示例
struct Foo{
//If all members are trivial enough and initialized,the constructor is constexpr by default.
int state=10;
//constexpr Foo()=default;
constexpr int bar(bool use_state){
if(use_state)
return state++;
else
return 0;// Literal
}
constexpr int get_state()const{
return state;
}
};
template<int arg>
void baz(){}
int main(int argc,char* argv[])
{
Foo foo;
//Carefull,this also implies const and ::bar() is non-const.
constexpr Foo c_foo;
foo.bar(true);//Run-time,`this` is not constexpr even though `true` is
foo.bar(false);//Compile-time,`this` was not needed,`false` is constexpr
bool* b = new bool{false};
foo.bar(*b);//Always run-time since `*b` is not constexpr
//Force compile-time evaluation in compile-time context
//Foo has constexpr constructor,creates non-const (temporary) constexpr instance
baz<Foo().bar(true)>();
baz<Foo().bar(false)>();
baz<foo.bar(false)>();
//ERROR,foo is not constexpr
//baz<foo.bar(true)>();
//ERROR,c_foo is const
//baz<c_foo.bar(false)>();
//Okay,c_foo is constexpr
baz<c_foo.get_state()>();
//ERROR,foo is not constexpr
//baz<foo.get_state()>();
return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。