Yukarıda da belirtildiği gibi, Boost.Preprocessor, C++ 0x kullanılamıyorsa gitmesi gereken yoldur, ancak sözdizimine alışması biraz zaman alır. Aşağıdaki örnek, Boost.Preprocessor'un değişken (ancak sınırlı) sayıdaki argümanlarla fonksiyonları tanımlamak için kullanılabileceğini göstermektedir.
#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()
önişlemci bu şekilde genişler: BOOST_PP_LOCAL_ITERATE()
tabi neden 0 parametrelerle çoğaltma başlar ama biz 1'den başlamak gerekir burada biz BOOST_PP_REPEAT(MAX_PARAMS, SQL_QUERY, ~)
kullanamaz,
$ 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();
}
}
Not, işte hangi daha esnektir.
Bunu beğendiniz mi? http://en.wikipedia.org/wiki/C%2B%2B0x#Variadic_templates – andrewdski
Evet, teşekkürler. Ancak, C++ 0x'den kaçınmaya çalışıyorum ve aynı zamanda fonksiyonu tanımlamanın tekrarlayıcı yolu da bu durumda işleri zorlaştırıyor. Sınırlı maksimum sayıda girişten memnun olduğum için belki başka bir yol var mı? – tom
, çeşit çeşit şablonların zarifçe kullanılmasının neredeyse bir yolu. Bu tür bir şablona dayalı düşünce alışmak biraz zaman alır, ancak muhtemelen değişken şablonlar olmadan yapacağınız her şeyden çok daha basit olacaktır. –