【发布时间】:2020-12-25 08:14:39
【问题描述】:
我正在编写一个简单的 C++ HTTP 服务器框架。在我的Server 课程中,我可以添加Route。每个路由都包含一个路径、一个 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\" }]";
},
}
);
既然如此,我想将add_route 函数设为constexpr,因为如果我错了,请纠正我,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's 不能是文字类型?有没有办法绕过这个限制?
下面是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&, HTTPResponse&, 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&, HTTPResponse&, Context&);
};
controller.cpp
#include "controller.hpp"
template <size_t N>
auto Controller<N>::empty_controller() -> Controller<1> {
return Controller<1>([](auto, auto, auto) {});
}
template <>
constexpr Controller<1>::Controller(Callable _callable) :
callables(std::array<Callable, 1> { std::move(_callable) }) { }
template <>
constexpr Controller<1>::Controller() :
Controller(empty_controller()) { }
template <size_t N>
constexpr Controller<N>::Controller(std::initializer_list<Callable> _list_callables) :
callables(_list_callables) { }
template <size_t N>
void Controller<N>::call(const HTTPRequest& req, HTTPResponse& res, Context& ctx) {
for (auto& callable : callables) {
callable(req, res, ctx);
}
}
【问题讨论】:
-
是的,
std::function不是文字类型。例如它没有constexpr构造函数。也许你可以传递一个函数指针,它应该可以工作。 -
一开始我考虑过使用函数指针,但后来我发现它们不允许我让
add_route语法看起来像我所做的那样干净。除此之外,正如我从接受的答案中发现的那样,制作add_routeconstexpr可能甚至不可能,或者可能不是有用的优化,因为该方法必须改变 @987654345 的状态@类。
标签: c++ c++11 lambda constexpr constexpr-function