C++函数式和泛型编程[使用MySQL连接器示例]
C++ functional & generic programming [with MySQL connector example]
我将使用MySQL连接器。它们提供了访问结果行的函数。例如getString(1)
, getInt(1)
, getDate(2)
。括号内的数字是结果的索引值。
所以我必须使用以下代码来访问这个示例行:'John', 'M', 34
string name = row.getString(1);
string sex = row.getString(2);
int age = row.getInt(3);
我想尝试泛型编程的各种原因(主要是为了好玩)。但很令人失望的是,即使花了很多时间,我也不能让它发生。
我想要的最终结果:
std::tie<name, sex, age> = row.getResult<string, string, int>();
这个函数应该调用相应的MySQL API。
也很高兴看到类似下面的答案,尽管语法是错误的。
std::tie<name, sex, age> = row.getResult([string, string, int]);
请不要建议使用for循环。让我们尝试一些更通用的&功能;-)
这个适合我:
struct Row
{
template <int N, typename ... Args> struct Helper;
template <typename Arg1> struct Helper<1, Arg1>
{
static std::tuple<Arg1> getResult(Row& r)
{
return std::make_tuple(r.getResult<Arg1>(0));
}
};
template <int N, typename Arg1, typename ... Args>
struct Helper<N, Arg1, Args...>
{
static std::tuple <Arg1, Args ...> getResult(Row& r)
{
return std::tuple_cat(std::make_tuple(r.getResult<Arg1>(N-1)),
Helper<N-1, Args...>::getResult(r));
}
};
template <typename Arg> Arg getResult(int index)
{
// This is where the value needs to be extracted from the row.
// It is a dummy implementation for testing purposes.
return Arg{};
}
template <typename ... Args>
std::tuple <Args ...> getResult()
{
return Helper<sizeof...(Args), Args...>::getResult(*this);
}
};
使用例子:
Row r;
auto res1 = r.getResult<std::string>();
auto res2 = r.getResult<int>();
auto res3 = r.getResult<int, double, int>();
auto res4 = r.getResult<int, int, double, double>();
auto res5 = r.getResult<std::string, std::string, int, int, double, double>();
工作代码:http://ideone.com/6IpJ8q
首先你需要写这些:
template<class T> T get( MySQLRow const& row, unsigned index);
template<>
int get<int>( MySQLRow const& row, unsigned index) { return connector.GetInt(index); }
// etc
然后,添加一些模板元编程工具:
template<class...>struct types{using type=types;};
上面的可以用std::tuple<?>*
代替types<?>
。也许吧。但无论如何,以上内容更清晰。
接下来,这可以用c++ 14的integral_sequence
:
template<unsigned...>struct indexes{using type=indexes;};
template<unsigned max, unsigned...is>struct make_indexes<max-1, max-1, is...>{};
template<unsigned...is>struct make_indexes<0,is...>:indexes<is...>{};
template<unsigned max>using make_indexes_t=typename make_indexes<max>::type;
最后,东西:
namespace details {
template<unsigned... Is, class... Types>
std::tuple< Types... >
getResult( indexes<Is...>, types<Types...>, MySQLRow const& row ) {
return { get<Types>( row, Is+1 )... };
}
}
template<class... Types>
std::tuple<Types...>
getResult( MySQLRow const& row ) {
return details::getResult( make_indexes_t<sizeof...(Ts)>{}, types<Types...>{}, row );
}
的语法是:
getResult<int, double, std::string>( row );
假设您编写了各种get
函数,并将MySQLRow
的类型固定为实际类型,并假设第一行是1
。
-
创建
Get
重载函数集,实现与GetX
方法的统一接口。#define DEFINE_GET_FOR_TYPE(Type, TypeName) void Get(Type& arg, const MySQLRow& row, std::size_t index) { arg = row.Get##TypeName(index); } DEFINE_GET_FOR_TYPE(int, Int) DEFINE_GET_FOR_TYPE(std::string, String) // ...
宏
DEFINE_GET_FOR_TYPE
用于创建必要的集合。 -
使用c++ 14
std::index_sequence
和std::make_index_sequence
实现GetResult
函数模板(它们也可以在c++ 11程序中实现):struct Iterate { Iterate(...) {} }; template <std::size_t... indices, typename... Types> void GetResultImpl(const MySQLRow& row, std::index_sequence<indices...>, Types&... args) { Iterate{(Get(args, row, indices + 1), 0)...}; } template <typename... Types> void GetResult(const MySQLRow& row, Types&... args) { GetResultImpl(row, std::make_index_sequence<sizeof...(Types)>(), args...); }
-
使用
GetResult
函数模板从行获取值:std::string name; std::string sex; int age; GetResult(row, name, sex, age);
现场演示
相关文章:
- 使用cmake从源代码构建MySQL连接器/C++失败(与以前的声明冲突)
- 使用mysql c++连接器的未定义引用
- MySQL C++连接器链接错误
- C++MySQL连接器没有utf8
- MySQL 连接器/C++.尝试在此过程中停止连接到数据库
- 如何使用连接器 c++ 在 mySQL 表二进制(16) 字段中存储 c++ 字节数组?
- MySQL C++连接器循环
- MySQL c++ 连接器:使用 SetBlob() 在查询中设置多个 blob 数据的正确方法是什么?
- 在 C/C++ 中使用 MySQL 连接器执行插入到表时出错
- 无法在我的ubuntu中正确安装MySQL连接器/c++
- 在 MySQL 连接器C++ API 中使用一个函数调用执行多个查询的正确方法是什么?
- mysql c ++连接器异常:用户"root"@'localhost'的访问被拒绝(使用密码:NO)&&MySQL服务器已消失
- MySQL 连接器 CPP 在 CentOS 6 中未定义的引用
- MySQL C++连接器:添加符号时出错:文件格式无法识别
- MySQL连接器C 结果集被缓冲
- 在 mysql 连接器中对 mysqlx 函数的未定义引用
- 我可以在不知道SQL的情况下使用SQLite或MySQL的C++连接器吗?
- 更新MySQL连接器后,隐式转换停止工作
- 批量插入 Mysql C++连接器
- 使用MySQL C 连接器从C 代码访问MEMSQL