可能有点夸张,主要是我之前一直没有用模板。代码的用途就是发送 HTTP 请求到 WEBHOOK,不同的 web hook 有不同的认证方式,还有一些没有认证方式。
我用的是 CPR 这个库进行发送。
为了逻辑简单,我第一次用了 variant,因为 cpr 的几个认证类都没有默认构造函数,导致我必须用 std::monostate 填充 variant 的第一个值。这就带来一个后果,cpr::PostCallback 或者 cpr::GettCallback 编译失败,因为它无法接受 std::monostate 作为参数。网上找了一些资料后,最终用 using T = std::decay_t<decltype(authParam)>; 和 std::is_same_v 解决了。
各位大牛是否有更简洁的方式解决?
有个很奇怪的问题,在 auto callback = [this, retryRequestPtr = std::move(retryRequestPtr)](cpr::Response r) 这一行,如果使用 std::move(retryRequestPtr),会导致程序崩溃因为后面访问 retryRequestPtr 时,它已经为空,改为 auto callback = [this, retryRequestPtr)](cpr::Response r) 就没有事了。
问题是:这个 callback 在这里只是定义一下,此时还没有实际执行到,为什么编译器就先把他给 move 为 nullptr 了?
// Prepare the callback
auto callback = [this, retryRequestPtr = std::move(retryRequestPtr)](cpr::Response r)
{
this->onResponse(retryRequestPtr->requestType, retryRequestPtr->sessionId, r, retryRequestPtr);
};
try
{
// Common parameters
cpr::Url url{retryRequestPtr->urlParams.url};
cpr::Timeout timeout{mTimeoutSecs * 1000};
// Build authentication
std::variant<std::monostate, cpr::Authentication, cpr::Bearer> auth;
if (retryRequestPtr->urlParams.auth == EventUrl::Auth::basic)
{
auth = cpr::Authentication{retryRequestPtr->urlParams.username, retryRequestPtr->urlParams.password, cpr::AuthMode::BASIC};
}
else if (retryRequestPtr->urlParams.auth == EventUrl::Auth::digest)
{
auth = cpr::Authentication{retryRequestPtr->urlParams.username, retryRequestPtr->urlParams.password, cpr::AuthMode::DIGEST};
}
else if (retryRequestPtr->urlParams.auth == EventUrl::Auth::bearer)
{
auth = cpr::Bearer{retryRequestPtr->urlParams.token};
}
// Create the request based on method and authentication
auto sendRequest = [&](auto& authParam)
{
using T = std::decay_t<decltype(authParam)>;
if (retryRequestPtr->requestType == RequestType::VersionRq)
{
if constexpr (!std::is_same_v<T, std::monostate>)
{
return cpr::GetCallback(callback, url, timeout, authParam, ssl, headers);
}
return cpr::GetCallback(callback, url, timeout, ssl, headers);
}
else
{
if constexpr (!std::is_same_v<T, std::monostate>)
{
return cpr::PostCallback(callback, url, timeout, authParam, body, ssl, headers);
}
return cpr::PostCallback(callback, url, timeout, body, ssl, headers);
}
};
// Dispatch the request
std::shared_ptr<cpr::AsyncWrapper<void, false>> requestFuture;
std::visit([&](auto& authParam)
{
auto f = std::make_shared<cpr::AsyncWrapper<void, false>>(sendRequest(authParam));
requestFuture = std::move(f);
}, auth);
// Store the future
{
std::scoped_lock lock(mMutex);
mFutureList.emplace_back(std::move(requestFuture));
}
}
catch (const std::exception& e)
{
status = false;
ErrLog(<< "Failed to send the HTTP request for request type = "
<< static_cast<uint32_t>(retryRequestPtr->requestType)
<< ", error: " << e.what());
}
--
修改:speedboy2998 FROM 218.76.62.*
FROM 218.76.62.*