Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c++;具有可变参数的模板函数 是否可以编写一个C++模板函数,它可以采用不同类型的输入变量变量(输入数量可以限制为10)? 例如,以函数sql\u exec()为例,该函数执行sql查询字符串,并将结果行保存在所提供类型的std向量中,即 std::vector<double> x,y; std::vector<std::string> s; std::string query="select * from ..."; sql_exec(query, s,x,y); // error if less than 3 rows or conversion not possible_C++_Templates_Template Meta Programming_Variadic Functions - Fatal编程技术网

c++;具有可变参数的模板函数 是否可以编写一个C++模板函数,它可以采用不同类型的输入变量变量(输入数量可以限制为10)? 例如,以函数sql\u exec()为例,该函数执行sql查询字符串,并将结果行保存在所提供类型的std向量中,即 std::vector<double> x,y; std::vector<std::string> s; std::string query="select * from ..."; sql_exec(query, s,x,y); // error if less than 3 rows or conversion not possible

c++;具有可变参数的模板函数 是否可以编写一个C++模板函数,它可以采用不同类型的输入变量变量(输入数量可以限制为10)? 例如,以函数sql\u exec()为例,该函数执行sql查询字符串,并将结果行保存在所提供类型的std向量中,即 std::vector<double> x,y; std::vector<std::string> s; std::string query="select * from ..."; sql_exec(query, s,x,y); // error if less than 3 rows or conversion not possible,c++,templates,template-meta-programming,variadic-functions,C++,Templates,Template Meta Programming,Variadic Functions,但实际上它是用gcc和-std=c++0x编译的。但是,显然sql\u query()仍然不接受可变长度的输入,需要使用两个向量调用。另外,我希望在大多数当前的编译器上使用一些可移植的东西。有什么明显我忽略的吗?我知道我可以改变设计,也许可以使用boost::tuple或其他东西,但我希望有这样一个简单的界面。在C++0x中,这是通过可变模板实现的(参数的数量可能会很大,限制是特定于实现的) 在C++03中,这是通过让预处理器宏生成大量不同算术性的模板函数来模拟的(参见Boost.preproc

但实际上它是用gcc和
-std=c++0x
编译的。但是,显然
sql\u query()
仍然不接受可变长度的输入,需要使用两个向量调用。另外,我希望在大多数当前的编译器上使用一些可移植的东西。有什么明显我忽略的吗?我知道我可以改变设计,也许可以使用
boost::tuple
或其他东西,但我希望有这样一个简单的界面。

在C++0x中,这是通过可变模板实现的(参数的数量可能会很大,限制是特定于实现的)

在C++03中,这是通过让预处理器宏生成大量不同算术性的模板函数来模拟的(参见Boost.preprocessor)


我已经使用C++03技术生成了从1到10个参数的“bind”,它工作得很好。

如上所述,Boost。如果C++0x不可用,预处理器是一种方法,尽管需要一段时间才能习惯语法。下面的示例演示如何使用Boost.Preprocessor定义具有可变(但数量有限)参数的函数

#include <boost/preprocessor/repetition.hpp>
#include <boost/preprocessor/iteration/local.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>

#define MAX_PARAMS  2

class sql {
public:
   // definition of the function in macro form
   #define SQL_QUERY_DEF(z, n, unused)                                     \
   template <BOOST_PP_ENUM_PARAMS(n, class T)>                             \
   void query(const std::string& query,                                    \
            BOOST_PP_ENUM_BINARY_PARAMS(n, const T, & x) );

   // does the actual code replication of SQL_QUERY_DEF
   #define BOOST_PP_LOCAL_MACRO(n)  SQL_QUERY_DEF(~, n, ~)
   #define BOOST_PP_LOCAL_LIMITS    (1, MAX_PARAMS)
   #include BOOST_PP_LOCAL_ITERATE()

   ...
};


// two helper functions:
// expands to var0.clear(); var1.clear(); ...
#define SQL_VECTOR_CLEAR(z,i,var) var##i.clear();
// expands to var0.push_back(this->get_col<T0>(0); ...
#define SQL_VECTOR_PUSH_BACK(z,i,var) var##i.push_back(this->get_col<T##i>(i));

// definition of the function in macro form
#define SQL_QUERY(z, n, unused)                                               \
template <BOOST_PP_ENUM_PARAMS(n, class T)>                                   \
void sql::query(const std::string& query,                                     \
                  BOOST_PP_ENUM_BINARY_PARAMS(n, std::vector< T,>& x) ){      \
   this->do_query(query);                                                     \
   if(this->num_cols()<n){                                                    \
      throw std::runtime_error();                                             \
   }                                                                          \
   BOOST_PP_REPEAT(n, SQL_VECTOR_CLEAR, x)                                    \
   while(this->is_open()) {                                                   \
      BOOST_PP_REPEAT(n, SQL_VECTOR_PUSH_BACK, x)                             \
      this->step();                                                           \
   }                                                                          \
}

// does the actual code replication of SQL_QUERY
#define BOOST_PP_LOCAL_MACRO(n)  SQL_QUERY(~, n, ~)
#define BOOST_PP_LOCAL_LIMITS    (1,  MAX_PARAMS)
#include BOOST_PP_LOCAL_ITERATE()
#包括
#包括
#包括
#定义最大参数2
类sql{
公众:
//宏形式的函数定义
#定义SQL_查询_定义(z,n,未使用)\
模板\
void查询(const std::string和query\
BOOST_PP_ENUM_BINARY_参数(n,const T,&x));
//SQL_QUERY_DEF的实际代码复制
#定义BOOST\u PP\u LOCAL\u宏(n)SQL\u QUERY\u DEF(~,n,~)
#定义增压PP本地限制(1,最大参数)
#包括BOOST_PP_LOCAL_ITERATE()
...
};
//两个辅助功能:
//展开为var0.clear();var1.clear()。。。
#定义SQL_VECTOR_CLEAR(z,i,var)var#i.CLEAR();
//扩展到var0。向后推(此->获取列(0)。。。
#定义SQL_VECTOR_PUSH_BACK(z,i,var)var#i.PUSH_BACK(this->get_col(i));
//宏形式的函数定义
#定义SQL_查询(z,n,未使用)\
模板\
void sql::query(const std::string和query)\
BOOST_PP_ENUM_BINARY_参数(n,std::vector&x)){\
此->执行查询(查询)\
如果(this->num\u cols()是\u open()){\
BOOST\u PP\u REPEAT(n,SQL\u VECTOR\u PUSH\u BACK,x)\
此->步骤()\
}                                                                          \
}
//SQL\u查询的实际代码复制
#定义BOOST\u PP\u LOCAL\u宏(n)SQL\u查询(~,n,~)
#定义增压PP本地限制(1,最大参数)
#包括BOOST_PP_LOCAL_ITERATE()
预处理器将其扩展为:

$ g++ -P -E sql.cpp | astyle

class sql {
public:
   template < class T0> void query(const std::string& query, const T0 & x0 );
   template < class T0 , class T1> void query(const std::string& query, const T0 & x0 , const T1 & x1 );
   ...
};
template < class T0> void sql::query(const std::string& query, std::vector< T0 >& x0 ) {
   this->do_query(query);
   if(this->num_cols()<1) {
      throw std::runtime_error();
   }
   x0.clear();
   while(this->is_open()) {
      x0.push_back(this->get_col<T0>(0));
      this->step();
   }
}
template < class T0 , class T1> void sql::query(const std::string& query, std::vector< T0 >& x0 , std::vector< T1 >& x1 ) {
   this->do_query(query);
   if(this->num_cols()<2) {
      throw std::runtime_error();
   }
   x0.clear();
   x1.clear();
   while(this->is_open()) {
      x0.push_back(this->get_col<T0>(0));
      x1.push_back(this->get_col<T1>(1));
      this->step();
   }
}
$g++-P-esql.cpp | astyle
类sql{
公众:
模板无效查询(const std::string&query,const T0&x0);
模板无效查询(常量std::string&query,常量T0&x0,常量T1&x1);
...
};
模板无效sql::查询(const std::string&query,std::vector&x0){
此->执行查询(查询);
如果(此->num\u cols()是\u open()){
x0.向后推(此->获取列(0));
此->步骤();
}
}
模板<类T0,类T1>无效sql::查询(常量std::字符串和查询,std::vector&x0,std::vector&x1){
此->执行查询(查询);
如果(此->num\u cols()是\u open()){
x0.向后推(此->获取列(0));
x1.向后推(此->获取列(1));
此->步骤();
}
}

注意,这里我们不能使用
BOOST\u PP\u REPEAT(MAX\u PARAMS,SQL\u QUERY,~)
,因为它用0个参数开始复制,但我们需要从1开始,这就是为什么
BOOST\u PP\u LOCAL\u ITERATE()
是必需的,它更灵活。

像这样吗?是的,谢谢。但是,我试图避免使用C++0x以及递归的函数定义方式,在这种情况下,这会使事情变得困难。因为我对有限的最大输入数感到满意,也许还有另一种方法?几乎肯定有一种方法可以优雅地使用可变模板。这基于模板的思维需要一点习惯,但它可能比没有可变模板的任何东西都要简单得多。
#include <boost/preprocessor/repetition.hpp>
#include <boost/preprocessor/iteration/local.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>

#define MAX_PARAMS  2

class sql {
public:
   // definition of the function in macro form
   #define SQL_QUERY_DEF(z, n, unused)                                     \
   template <BOOST_PP_ENUM_PARAMS(n, class T)>                             \
   void query(const std::string& query,                                    \
            BOOST_PP_ENUM_BINARY_PARAMS(n, const T, & x) );

   // does the actual code replication of SQL_QUERY_DEF
   #define BOOST_PP_LOCAL_MACRO(n)  SQL_QUERY_DEF(~, n, ~)
   #define BOOST_PP_LOCAL_LIMITS    (1, MAX_PARAMS)
   #include BOOST_PP_LOCAL_ITERATE()

   ...
};


// two helper functions:
// expands to var0.clear(); var1.clear(); ...
#define SQL_VECTOR_CLEAR(z,i,var) var##i.clear();
// expands to var0.push_back(this->get_col<T0>(0); ...
#define SQL_VECTOR_PUSH_BACK(z,i,var) var##i.push_back(this->get_col<T##i>(i));

// definition of the function in macro form
#define SQL_QUERY(z, n, unused)                                               \
template <BOOST_PP_ENUM_PARAMS(n, class T)>                                   \
void sql::query(const std::string& query,                                     \
                  BOOST_PP_ENUM_BINARY_PARAMS(n, std::vector< T,>& x) ){      \
   this->do_query(query);                                                     \
   if(this->num_cols()<n){                                                    \
      throw std::runtime_error();                                             \
   }                                                                          \
   BOOST_PP_REPEAT(n, SQL_VECTOR_CLEAR, x)                                    \
   while(this->is_open()) {                                                   \
      BOOST_PP_REPEAT(n, SQL_VECTOR_PUSH_BACK, x)                             \
      this->step();                                                           \
   }                                                                          \
}

// does the actual code replication of SQL_QUERY
#define BOOST_PP_LOCAL_MACRO(n)  SQL_QUERY(~, n, ~)
#define BOOST_PP_LOCAL_LIMITS    (1,  MAX_PARAMS)
#include BOOST_PP_LOCAL_ITERATE()
$ g++ -P -E sql.cpp | astyle

class sql {
public:
   template < class T0> void query(const std::string& query, const T0 & x0 );
   template < class T0 , class T1> void query(const std::string& query, const T0 & x0 , const T1 & x1 );
   ...
};
template < class T0> void sql::query(const std::string& query, std::vector< T0 >& x0 ) {
   this->do_query(query);
   if(this->num_cols()<1) {
      throw std::runtime_error();
   }
   x0.clear();
   while(this->is_open()) {
      x0.push_back(this->get_col<T0>(0));
      this->step();
   }
}
template < class T0 , class T1> void sql::query(const std::string& query, std::vector< T0 >& x0 , std::vector< T1 >& x1 ) {
   this->do_query(query);
   if(this->num_cols()<2) {
      throw std::runtime_error();
   }
   x0.clear();
   x1.clear();
   while(this->is_open()) {
      x0.push_back(this->get_col<T0>(0));
      x1.push_back(this->get_col<T1>(1));
      this->step();
   }
}