是否有一个模板可以生成类的静态/动态绑定版本

Is there a template that can generate static / dynamically bound versions of a class?

本文关键字:静态 版本 动态绑定 有一个 是否      更新时间:2023-10-16

我正在编写一些库代码,我希望用户能够利用静态绑定(如果可以的话)。如果他们无法在编译时实例化一个类,我希望有一个动态版本的类,这样它就可以在运行时实例化。

举个简单的例子,假设我有一个结构模板a:

template<bool dynamic, int value=0> struct A
{
    static const int Value = value;
};

template<> struct A<true>
{
    int Value;
    A(int value) : Value(value) {}
};

这些定义允许库的用户静态和动态地实例化A:

A<true> dynamicA = A<true>(5);
A<false, 5> staticA;

这个方法的问题是我必须写两次类的定义。我可以想出几种方法来实现一个模板,该模板将自己生成两个版本,但我可以看到这将成为一项艰巨的工作。特别是对于使用不同数量参数的类,例如:

// It would be much harder to generate a static version of this class, 
// though it is possible with type lists.  Also, the way I'm imagining it, 
// the resulting classes probably wouldn't be very easy to use.
struct A
{
   vector<int> Values;
    A(vector<int> value) : Values(value) {}
};

这个模式/问题有名字吗?有没有一个元编程库,它有可以为我生成这两个定义的模板?我该如何避免两次编写类的定义?

有一种简单的机制可以将不依赖于动态/静态值问题的部分放在一个位置:将它们放在另一个类中,我们称之为basic_A,并将问题中显示的静态/动态值容器称为value_A。有不同的方法连接value_Abasic_A以形成完整的A类:

  1. basic_Avalue_A内部的聚合。这意味着您必须将basic_A的每个方法路由到value_A,并在value_A的两个专业化中提供相应的一行。这可能并没有多大好处,因为您必须复制所有的一行代码,所以请注意。

  2. value_Abasic_A内部的聚合。您要么也必须将basic_A作为模板,只需将参数传递给value_A,并为这两种专门化提供正确的构造函数,可能会通过SFINAE以某种方式禁用和启用它们。也不是一段非常漂亮和可维护的代码。另一种选择是为value_A的两个专门化创建一个公共基类(Interface),在basic_A中为该接口创建一个unique_ptr,并将已构建好的value_A传递到basic_A的构造函数中,代价是无论何时您都要访问该值,都要使用虚拟函数调用和poitner间接方法。尤克,尤其是如果A是一个小型且快速的轻量级。

  3. value_A继承basic_A。与2中的问题相同。apply,关于构造函数和模板参数的转发。

  4. basic_A继承value_A。构造问题消失了,但现在basic_A不能很容易地访问value_A的值。一种解决方案是在basic_A中具有纯虚拟函数getValue()value_A的两个专业化必须实现该函数。这再次带来了虚拟函数调度的成本,这对于小型轻量级类来说可能是不可取的,但它支持封装,因为basic_A是一个非模板,可以将其实现隐藏在.cpp文件中。另一种方法是在CRTP中使用compiletime多态性,这将使basic_A再次成为模板。

以下是4的两种方法的两个示例。:

4a:getValue()作为虚拟函数:

//basic_a.hpp
struct basic_A {
  int foo() const;
  virtual int getValue() const = 0;
};
//basic_A.cpp
int basic_A::foo() const { return 10 * getValue(); }

4b:getValue() vía CRTP

template <class Value_t>
struct basic_A {
  int foo() const { return 10 * value_(); }
private:
  int value_() const { return static_cast<Value_t const&>(*this).getValue(); }
};

模板CCD_ 34,又名。4b的CCD_ 35。对于4a,它几乎是一样的,只是丢失了basic_A中的模板参数和括号,因为它是一个普通类:

template <bool dyn, int value = 0> 
struct A;
template <>
struct A<true, 0> : basic_A<A<true, 0>>
{
  int val;
  int getValue() const { return val; }
};
template <int value>
struct A<false, value> : basic_A<A<false,value>>
{
  int geValue() { return value; }
};