给出以下片段
#include <stdexcept>
#include <vector>
#include <iostream>
#include <ostream>
#include <sstream>
namespace tools {
namespace error {
template<typename Base>
struct wallet_error_base : public Base {
const std::string &location() const { return m_loc; }
std::string to_string() const {
std::ostringstream ss;
ss << m_loc << ':' << typeid(*this).name() << ": " << Base::what();
return ss.str();
}
protected:
wallet_error_base(std::string &&loc, const std::string &message)
: Base(message), m_loc(loc) {
}
private:
std::string m_loc;
};
typedef wallet_error_base<std::logic_error> wallet_logic_error;
struct wallet_rpc_error : public wallet_logic_error {
const std::string &request() const { return m_request; }
std::string to_string() const {
std::ostringstream ss;
ss << wallet_logic_error::to_string() << ", request = " << m_request;
return ss.str();
}
protected:
explicit wallet_rpc_error(std::string &&loc, const std::string &message, const std::string &request)
: wallet_logic_error(std::move(loc), message), m_request(request) {
}
private:
std::string m_request;
};
struct wallet_generic_rpc_error : public wallet_rpc_error {
explicit wallet_generic_rpc_error(std::string &&loc, const std::string &request, const std::string &status)
: wallet_rpc_error(std::move(loc), std::string("error in ") + request + " RPC: " + status, request),
m_status(status) {
}
const std::string &status() const { return m_status; }
private:
const std::string m_status;
};
// Base case for the variadic template recursion
template<typename TException>
void throw_wallet_ex(std::string&& loc) {
TException e(std::move(loc));
std::cout << e.to_string();
throw e;
}
// Recursive variadic template function to accept a variable number of string arguments
template<typename TException, typename... Args>
void throw_wallet_ex(std::string&& loc, const Args& ... args) {
TException e(std::move(loc), args...);
std::cout << e.to_string();
throw e;
}
}
}
#define THROW_ON_RPC_RESPONSE_ERROR(r, error, res, method, ...) \
do { \
std::cout << "Doing work here"; \
THROW_WALLET_EXCEPTION_IF(res.status != "ok", ## __VA_ARGS__); \
} while(0)
#define THROW_ON_RPC_RESPONSE_ERROR_GENERIC(r, err, res, method) \
THROW_ON_RPC_RESPONSE_ERROR(r, err, res, method, tools::error::wallet_generic_rpc_error, method, res.status)
#define STRINGIZE_DETAIL(x) #x
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
#define THROW_WALLET_EXCEPTION_IF(cond, err_type, ...) \
if (cond) \
{ \
std::cerr << #cond << ". THROW EXCEPTION: " << #err_type; \
tools::error::throw_wallet_ex<err_type>(std::string(__FILE__ ":" STRINGIZE(__LINE__)), ## __VA_ARGS__); \
}
struct result {
result(const std::string& status) : status(status) {
}
std::string status;
};
int main() {
result res("ok");
THROW_ON_RPC_RESPONSE_ERROR_GENERIC(true, {}, res, "rpc_access_submit_nonce");
return 0;
}
我收到错误
ERROR: C:/users/katso/documents/github/denarii/src/BUILD:1161:10: Compiling src/example_of_error.cpp failed: (Exit 2): cl.exe failed:
error executing CppCompile command (from target //src:example_of_error) C:\Program Files (x86)\Microsoft Visual Studio\2022\Community\
VC\Tools\MSVC\14.30.30705\bin\HostX64\x64\cl.exe ... (remaining 1 argument skipped)
cl : Command line warning D9002 : ignoring unknown option '-O3'
cl : Command line warning D9002 : ignoring unknown option '-std=c++17'
cl : Command line warning D9002 : ignoring unknown option '-std=c++17'
src/example_of_error.cpp(109): error C2672: 'tools::error::throw_wallet_ex': no matching overloaded function found
src/example_of_error.cpp(109): error C2974: 'tools::error::throw_wallet_ex': invalid template argument for 'Args', type expected
src/example_of_error.cpp(74): note: see declaration of 'tools::error::throw_wallet_ex'
src/example_of_error.cpp(109): error C2977: 'tools::error::throw_wallet_ex': too many template arguments
src/example_of_error.cpp(66): note: see declaration of 'tools::error::throw_wallet_ex'
Target //src:example_of_error failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 5.192s, Critical Path: 0.38s
INFO: 2 processes: 2 internal.
ERROR: Build did NOT complete successfully
这是 Windows 10,带有来自 msys2 的 gcc 13.2.0,使用 bazel 7.0
当我将鼠标悬停在对“THROW_ON_RPC_RESPONSE_ERROR_GENERIC”的调用上时,Clion 向我展示了这一点
do {
std::cout << "Doing work here";
if (res.status != "ok") {
std::cerr << "res.status != \"ok\"" << ". THROW EXCEPTION: " << "tools::error::wallet_generic_rpc_error";
tools::error::throw_wallet_ex<tools::error::wallet_generic_rpc_error>(std::string("_file_name_" ":" "106"),
"rpc_access_submit_nonce", res.status);
};
}
while (0)
据我所知,使用 3 个字符串参数调用可变参数模板函数应该可以工作。