C ++功能&通用编程[使用MySQL连接器示例]

时间:2014-08-20 18:46:27

标签: c++ templates functional-programming generic-programming

我打算使用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循环。让我们尝试一些更通用的东西。功能性的; - )

3 个答案:

答案 0 :(得分:1)

这对我有用:

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

答案 1 :(得分:0)

首先你需要写下这些:

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

答案 2 :(得分:0)

  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用于创建必要的集合。

  2. 使用C ++ 14 GetResultstd::index_sequencethey can be implemented in C++11 program, too)实施std::make_index_sequence功能模板:

    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...);
    }
    
  3. 使用GetResult函数模板从行中获取值:

    std::string name;
    std::string sex;
    int age;
    
    GetResult(row, name, sex, age);
    
  4. Live demo