检测字段或成员getter是否为主键的技术

时间:2014-11-17 08:06:48

标签: c++ template-meta-programming

我正在对算法实施优化。

优化包括在结构中值已知为唯一时立即停止搜索。为了明白这一点,想象一下我的结构就像一个数据库表,具有唯一值的字段将等同于"主键"在关系数据库中。

如果我知道该字段的值是唯一的,那么我想调度一个在找到第一次出现值时急切停止的实现。我在编译时通过设计知道这一点。

所以我想检测一个给定的字段值在编译时是唯一的。

我的功能如下:

template <class Storage, class Getter, class Value>
vector<MyStruct> select_records(Storage const & s, Getter g, Value const & v);

此功能将发送:

  • 如果作为成员指针的Getter是&#34;主键&#34;,那么它将调度到优化的实现。
  • 否则,调度到遍历所有存储的实现。

我怎样才能实现&#34;主键&#34;检测?约束:解决方案必须是非侵入式的。

1 个答案:

答案 0 :(得分:2)

根据您提供的信息,无法在编译时执行您想要的操作。 Getter只是一种类型,并且您说您无法单独按类型识别主键。这意味着您不会根据Getter(类型)进行识别,而是基于g,即运行时值。当然,没有编译时访问运行时值。

如果可能,您可以通过将g转换为编译时信息来实现此目的,如下所示:

template <class Storage, class Value, Value Storage::*getter>
vector<MyStruct> select_records(Storage const & s, Value const & v);

然后将其专门化为getter的已知值,这些值对应于主键。


当然,上面要求你明确指定所有模板参数(因为你要指定的那个,getter,是最后一个),并且并不真正好玩,因为函数模板不能部分专业化。这里提供了一些更好的语法和专业化选项:

template <class Storage, class Value>
Selector<Storage, Value> record_selector(Storage const & s, Value const & v)
{
  return Selector<Storage, Value>(s, v);
}


template <class Storage, class Value>
class Selector
{
  Storage const & s;
  Value const & v;

public:
  Selector(Storage const & s, Value const & v) : s(s), v(v) {}

  template <Value Storage::*getter>
  vector<MyStruct> select()
  {
    return Select_Impl<Storage, Value, getter, IsPrimaryKey<Storage, Value, getter>::value>::call(s, v);
  }
};


template <class Storage, class Value, Value Storage::*getter, bool primary>
struct Select_Impl
{
  static vector<MyStruct> call(Storage const & s, Value const & v)
  {
    // Normal implementation.
  }
};


template <class Storage, class Value, Value Storage::*getter>
struct Select_Impl<Storage, Value, getter, true>
{
  static vector<MyStruct> call(Storage const & s, Value const & v)
  {
    // Optimised implementation
  }
};


template <class Storage, class Value, Value Storage::*getter>
struct IsPrimaryKey
{
  static const bool value = false;
};
// Specialise the above for each primary key with `value` set to `true`
// This should be possible, since you said you know the set of primary keys at compile-time

在代码中,您应该能够像这样使用它:

vector<MyStruct> res = record_selector(s, v).select<&SomeStorage::someMember>();