C++20 - 模板参数 deduction/substitution 问题
C++20 - Template argument deduction/substitution problem
我正在尝试使用 pqxx 将函数 sql_exec
写入 Postgresql 数据库中的 运行 可序列化事务,但我仍然失败,因为模板参数 deduction/substitution 问题。
我试过多次重写模板函数,但我真的不知道,哪里错了,不明白,为什么编译器returns错误。
这是函数
namespace kp{
pqxx::connection get_conn();
int txn_rep();
using txn_rlbck = pqxx::transaction_rollback;
using t_txn = pqxx::transaction<pqxx::serializable>;
using t_con = pqxx::connection;
class txn_gen{
t_con& con;
int enu = 0;
public:
txn_gen(t_con& con) : con(con){};
void except(const txn_rlbck& ex);
t_txn txn();
};
template<typename t_function, typename... t_args>
std::invoke_result_t<std::decay_t<t_function>, std::decay_t<t_txn&>, std::decay_t<t_args>...> sql_exec(t_con& conn, t_function&& f, t_args&&... args){
txn_gen gen(conn);
while(true){
try{
auto&& txn = gen.txn();
auto&& ret = f(txn, args...);
txn.commit();
return ret;
}
catch(txn_rlbck& ex){
gen.except(ex);
}
}
}
};
然后我在这个lambda中使用了它
auto map_deamon = [this]{
while(true){
std::this_thread::sleep_for(to_duration(settings.update_map_period));
t_con conn = get_conn();
std::unique_lock<std::mutex> lock(map_overload_mutex);
auto&& reload = [this, &lock](t_txn& txn){
mp::tt_map new_map = obtain_map(txn, settings, walk_machine, car_machine);
lock.lock();
map = std::make_shared<mp::tt_map> (std::move(new_map));
};
sql_exec(conn, reload);
}
};
并且编译器返回了这个错误
src/path_planner.cpp: In lambda function:
src/path_planner.cpp:61:32: error: no matching function for call to ‘sql_exec(kp::t_con&, kp::server_instance::boot()::<lambda()>::<lambda(kp::t_txn&)>&)’
sql_exec(conn, reload);
^
In file included from src/path_planner.cpp:12:
include/sql.hpp:27:99: note: candidate: ‘template<class t_function, class ... t_args> std::invoke_result_t<typename std::decay<_Tp>::type, pqxx::transaction<(pqxx::isolation_level)2, (pqxx::readwrite_policy)1>, std::decay_t<t_args>...> kp::sql_exec(kp::t_con&, t_function&&, t_args&& ...)’
std::invoke_result_t<std::decay_t<t_function>, std::decay_t<t_txn&>, std::decay_t<t_args>...> sql_exec(t_con& conn, t_function&& f, t_args&&... args){
^~~~~~~~
include/sql.hpp:27:99: note: template argument deduction/substitution failed:
src/path_planner.cpp: In function ‘void kp::boot()’:
你能给我建议一下吗,问题出在哪里?
谢谢。
您的方法是 SFINAEd,因为 reload(std::declval<t_txn>())
无效(reload(std::declval<t_txn&>())
有效)
您可能会使用 decltype(auto)
template<typename t_function, typename... t_args>
decltype(auto)
sql_exec(t_con& conn, t_function&& f, t_args&&... args)
或去掉std::decay
(尤其是t_txn&
):
template<typename t_function, typename... t_args>
std::invoke_result_t<t_function, t_txn&, t_args...>
sql_exec(t_con& conn, t_function&& f, t_args&&... args)
我正在尝试使用 pqxx 将函数 sql_exec
写入 Postgresql 数据库中的 运行 可序列化事务,但我仍然失败,因为模板参数 deduction/substitution 问题。
我试过多次重写模板函数,但我真的不知道,哪里错了,不明白,为什么编译器returns错误。
这是函数
namespace kp{
pqxx::connection get_conn();
int txn_rep();
using txn_rlbck = pqxx::transaction_rollback;
using t_txn = pqxx::transaction<pqxx::serializable>;
using t_con = pqxx::connection;
class txn_gen{
t_con& con;
int enu = 0;
public:
txn_gen(t_con& con) : con(con){};
void except(const txn_rlbck& ex);
t_txn txn();
};
template<typename t_function, typename... t_args>
std::invoke_result_t<std::decay_t<t_function>, std::decay_t<t_txn&>, std::decay_t<t_args>...> sql_exec(t_con& conn, t_function&& f, t_args&&... args){
txn_gen gen(conn);
while(true){
try{
auto&& txn = gen.txn();
auto&& ret = f(txn, args...);
txn.commit();
return ret;
}
catch(txn_rlbck& ex){
gen.except(ex);
}
}
}
};
然后我在这个lambda中使用了它
auto map_deamon = [this]{
while(true){
std::this_thread::sleep_for(to_duration(settings.update_map_period));
t_con conn = get_conn();
std::unique_lock<std::mutex> lock(map_overload_mutex);
auto&& reload = [this, &lock](t_txn& txn){
mp::tt_map new_map = obtain_map(txn, settings, walk_machine, car_machine);
lock.lock();
map = std::make_shared<mp::tt_map> (std::move(new_map));
};
sql_exec(conn, reload);
}
};
并且编译器返回了这个错误
src/path_planner.cpp: In lambda function:
src/path_planner.cpp:61:32: error: no matching function for call to ‘sql_exec(kp::t_con&, kp::server_instance::boot()::<lambda()>::<lambda(kp::t_txn&)>&)’
sql_exec(conn, reload);
^
In file included from src/path_planner.cpp:12:
include/sql.hpp:27:99: note: candidate: ‘template<class t_function, class ... t_args> std::invoke_result_t<typename std::decay<_Tp>::type, pqxx::transaction<(pqxx::isolation_level)2, (pqxx::readwrite_policy)1>, std::decay_t<t_args>...> kp::sql_exec(kp::t_con&, t_function&&, t_args&& ...)’
std::invoke_result_t<std::decay_t<t_function>, std::decay_t<t_txn&>, std::decay_t<t_args>...> sql_exec(t_con& conn, t_function&& f, t_args&&... args){
^~~~~~~~
include/sql.hpp:27:99: note: template argument deduction/substitution failed:
src/path_planner.cpp: In function ‘void kp::boot()’:
你能给我建议一下吗,问题出在哪里?
谢谢。
您的方法是 SFINAEd,因为 reload(std::declval<t_txn>())
无效(reload(std::declval<t_txn&>())
有效)
您可能会使用 decltype(auto)
template<typename t_function, typename... t_args>
decltype(auto)
sql_exec(t_con& conn, t_function&& f, t_args&&... args)
或去掉std::decay
(尤其是t_txn&
):
template<typename t_function, typename... t_args>
std::invoke_result_t<t_function, t_txn&, t_args...>
sql_exec(t_con& conn, t_function&& f, t_args&&... args)