C++ 获取C+的序号+;可变模板参数
我想从C++ 获取C+的序号+;可变模板参数,c++,c++11,templates,c++14,variadic-templates,C++,C++11,Templates,C++14,Variadic Templates,我想从可变模板参数中检索每个参数的索引,目前我正在使用这种方法: 从第三方库: struct statement { template <typename T> void bind(int, T t) { // .... } }; 我的问题是:有没有更好的方法来实现这一点,即获得变量模板的序数 编辑: 我想使用这个实现包装sql准备语句,并将特定参数绑定到特定索引。 下面是一个我想包装的代码示例,我想调用bind\u all prepare(stmt, &quo
可变模板
参数中检索每个参数的索引,目前我正在使用这种方法:
从第三方库:
struct statement {
template <typename T>
void bind(int, T t) { // ....
}
};
我的问题是:有没有更好的方法来实现这一点,即获得变量模板的序数
编辑:
我想使用这个实现包装sql准备语句
,并将特定参数绑定到特定索引。
下面是一个我想包装的代码示例,我想调用bind\u all
prepare(stmt, "insert into tab (a, b) values (?, ?);");
const int eight_int = 8;
stmt.bind(0, &eight_int);
const string eight_str = "eight";
stmt.bind(1, eight_str.c_str());
execute(stmt);
具有简单的扩展(可以在C++17中使用a)
具有简单的扩展(可以在C++17中使用a)
您可以使用
std::index_sequence
创建包含匹配索引的第二个模板参数包:
template <typename... Args, size_t... Is>
void bind_all_helper(std::index_sequence<Is...>, Args... args) {
int dummy[]{(bind<Is>(args), 0)...};
(void)dummy; // just to avoid unused variable warnings
}
template <typename... Args>
void bind_all(Args... args) {
bind_all_helper(std::make_index_sequence<sizeof...(args)>{}, args...);
}
数组的每个元素最终都是0
,但其求值会产生调用bind(arg)
的副作用
使用C++17,可以用折叠表达式替换
伪数组定义,但如果您仅限于C++14,则显然不能使用折叠表达式。您可以使用std::index_sequence
创建包含匹配索引的第二个模板参数包:
template <typename... Args, size_t... Is>
void bind_all_helper(std::index_sequence<Is...>, Args... args) {
int dummy[]{(bind<Is>(args), 0)...};
(void)dummy; // just to avoid unused variable warnings
}
template <typename... Args>
void bind_all(Args... args) {
bind_all_helper(std::make_index_sequence<sizeof...(args)>{}, args...);
}
数组的每个元素最终都是0
,但其求值会产生调用bind(arg)
的副作用
对于C++17,可以用折叠表达式替换伪数组定义,但如果您仅限于C++14,那么显然这不是一个选项。为什么不为此使用std::tuple
#include <utility>
#include <tuple>
template<typename T, std::size_t... Index>
void doBind(Statement& st, T const& tuple, std::index_sequence<Index...> const&)
{
// Using C++17 fold expression
((st.bind(Index, std::get<Index>(tuple))),...);
// Using C++11 dummy variable
int dummy[] = {0, (st.bind(Index, std::get<Index>(tuple)),0)...};
(void)dummy; // to prevent unused variable warning.
}
template<typename... Args>
void prepare(std::string const& sql, Args&&... args)
{
Statement statement;
prepare(statement, sql);
doBind(statement, std::make_tuple(args...), std::make_index_sequence<sizeof...(args)>());
execute(statement);
}
#包括
#包括
模板
void-doBind(语句&st,T常量和元组,std::index\u序列常量&)
{
//使用C++17倍表达式
((st.bind(Index,std::get(tuple)),…);
//使用C++11虚拟变量
int-dummy[]={0,(st.bind(Index,std::get(tuple)),0);
(void)dummy;//防止未使用变量警告。
}
模板
void prepare(std::string const&sql,Args&&…Args)
{
声明;
准备(语句、sql);
doBind(语句,std::make_tuple(args…,std::make_index_sequence());
执行(声明);
}
为什么不为此使用std::tuple
#include <utility>
#include <tuple>
template<typename T, std::size_t... Index>
void doBind(Statement& st, T const& tuple, std::index_sequence<Index...> const&)
{
// Using C++17 fold expression
((st.bind(Index, std::get<Index>(tuple))),...);
// Using C++11 dummy variable
int dummy[] = {0, (st.bind(Index, std::get<Index>(tuple)),0)...};
(void)dummy; // to prevent unused variable warning.
}
template<typename... Args>
void prepare(std::string const& sql, Args&&... args)
{
Statement statement;
prepare(statement, sql);
doBind(statement, std::make_tuple(args...), std::make_index_sequence<sizeof...(args)>());
execute(statement);
}
#包括
#包括
模板
void-doBind(语句&st,T常量和元组,std::index\u序列常量&)
{
//使用C++17倍表达式
((st.bind(Index,std::get(tuple)),…);
//使用C++11虚拟变量
int-dummy[]={0,(st.bind(Index,std::get(tuple)),0);
(void)dummy;//防止未使用变量警告。
}
模板
void prepare(std::string const&sql,Args&&…Args)
{
声明;
准备(语句、sql);
doBind(语句,std::make_tuple(args…,std::make_index_sequence());
执行(声明);
}
听起来有点像XY问题。你能告诉我你想做什么吗?如果同一类型在bind_all
中出现两次怎么办?@NathanOliver,我刚刚更新了我的问题。看起来std::tuple
可能会有所帮助。将允许同样的类型存在两次。@AndyG,好吧,我将使用它在特定的索引处绑定它。听起来有点像XY问题。你能告诉我你想做什么吗?如果同一类型在bind_all
中出现两次怎么办?@NathanOliver,我刚刚更新了我的问题。看起来std::tuple
可能会有所帮助。将允许同样的类型有两次。@AndyG,好吧,我将使用它在特定的索引处绑定它。通过多一点样板文件,我们可以在编译时计算索引,但这很简单。如果所有那些idx++
s保证以正确的顺序进行计算,在C++17之前?@miles,逗号运算符引入了排序,所以yes@AndyG,谢谢,但我不能使用c++17…@ElvisOric我展示的答案和演示可以在c++11或14中运行。折叠表达式,我没有用过,是c++17,再加上一点样板,我们可以在编译时计算索引,但这很简单。所有那些idx++
s都保证按正确的顺序计算。在c++17之前,逗号操作符引入了排序,所以yes@AndyG非常感谢。但是我不能使用c++17…@ElvisOric我展示的答案和演示可以在c++11或14中运行。折叠表达式,我没有使用过,是c++17,我使用的是第三方库。该库提供了prepare
函数,而不带out param for语句。如果我想绑定6个参数,我需要编写6次语句。bind(index,param)
和我想自动化的部分。另外,若我在查询中添加另一个参数,我需要将所有其他参数移动一个。我只想这样使用它:bind_all(1,1.24f,3.14,“Hello”,std::string{“World”},true)
@ElvisOric解决了吗?这个解决方案使用的是c++17?我得到的“折叠表达式仅适用于'-std=c++17'”?我使用的是第三方库。该库提供了prepare
函数,而不带out param for语句。如果我想绑定6个参数,我需要编写6次语句。bind(index,param)
和我想自动化的部分。另外,若我在查询中添加另一个参数,我需要将所有其他参数移动一个。我只想这样使用它:bind_all(1,1.24f,3.14,“Hello”,std::string{“World”},true)
@ElvisOric解决了吗?这个解决方案使用的是c++17?我得到的是“折叠表达式仅适用于'-std=c++17'”?使用:int-dummy[]{0,(bind
用于args
为空的情况。使用:int-dummy[]{0,(bind
用于args
为空的情况。
template <typename... Args, size_t... Is>
void bind_all_helper(std::index_sequence<Is...>, Args... args) {
int dummy[]{(bind<Is>(args), 0)...};
(void)dummy; // just to avoid unused variable warnings
}
template <typename... Args>
void bind_all(Args... args) {
bind_all_helper(std::make_index_sequence<sizeof...(args)>{}, args...);
}
int dummy[] {
(bind<0>(1), 0),
(bind<1>(3.14), 0)
};
#include <utility>
#include <tuple>
template<typename T, std::size_t... Index>
void doBind(Statement& st, T const& tuple, std::index_sequence<Index...> const&)
{
// Using C++17 fold expression
((st.bind(Index, std::get<Index>(tuple))),...);
// Using C++11 dummy variable
int dummy[] = {0, (st.bind(Index, std::get<Index>(tuple)),0)...};
(void)dummy; // to prevent unused variable warning.
}
template<typename... Args>
void prepare(std::string const& sql, Args&&... args)
{
Statement statement;
prepare(statement, sql);
doBind(statement, std::make_tuple(args...), std::make_index_sequence<sizeof...(args)>());
execute(statement);
}