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);
}