基于模板的动态数据类型选择

Dynamic data type choosing based on template

本文关键字:数据类型 选择 动态 于模板      更新时间:2023-10-16

假设我有这样一个对象:

class Spline {
public:
    Spline(std::size_t const dim);
    // Quite a few functions here. One of those:
    vec operator()(double const t) const; // Returns vector of dimension d
}

现在,在这个类的大多数使用中,维数将在编译时确定,因此(出于性能原因)像这样更改类是一个好主意:

template <std::size_t dim>
class Spline {
public:
    Spline();
    // Quite a few functions here. One of those:
    vec::fixed<dim> operator()(double const t) const; // Returns vector of dimension d
}

(vecvec::fixed是由犰狳线性代数库定义的对象)。现在我想有两个版本生活在并行,从而能够选择维度在编译时以及在运行时。简而言之,我想创建vec::fixed<dim>Spline::fixed<dim>的等价物,但不需要两次实现所有功能。特别是,我必须根据是否存在模板参数来选择所有这些函数的返回类型。

你知道我该如何做到这一点吗,特别是考虑到一个清晰和可维护的设计?(希望我把自己说得很清楚,虽然我不是很确定)

使用一个简单的traits元结构并特殊化它。

template<std::size_t dim>
struct spline_return_traits{
  typedef vec::fixed<dim> type;
};
template<>
struct spline_return_traits<0>{ // 0 is a special marker for runtime dimensions
  typedef vec type;
};
template<std::size_t dim>
class Spline_impl{
  typedef typename spline_return_traits<dim>::type spline_return;
public:
  spline_return operator()(double const t) const;
// if <dim> is 0, then the dynamic vec will be chosen as the return type
  // all your functions
};
class Spline : public Spline_impl<0>{ // default is dynamic
public:
  template<int dim>
  struct fixed : public Spline_impl<dim>{
  };
};

现在你简单地使用它。Spline_impl的每个操作符、构造函数和函数都应该在子类中可用。对于每个函数的实现,您需要做一些分支,必须在运行时或固定vec之间做出决定:

if(dim == 0){
  // runtime specific stuff
}else{
  // compile-time specific stuff
}
使用

:

Spline dynamic_spline;
Spline::fixed<10> fixed_10_spline;

唯一的问题是Spline类的大小将是Spline_impl的两倍…:/让我想想是否也能找到解决办法。
编辑:如果您不希望Spline的大小是Spline_impl的两倍,一种可能性是添加一点冗长和typedef:

class Spline : public Spline_impl<0>{ // default is dynamic size
public:
  template<std::size_t dim>
  struct fixed{
    typedef Spline_impl<dim> type;
  };
};

和as

Spline dynamic_spline;
typename Spline::fixed<10>::type fixed_10_spline;

如果我正确理解你的问题,你想要一个struct的编译时使用和运行时使用以及最好的名称相同。在我看来,您可以将class声明为template,然后专门化它的一个实例(例如size_t = 0xffffffff),您可能不会使用该实例。您可以在该实例中声明所有用于运行时使用的定义。

例如,

template<std::size_t dim = ~0> // choose default dimension(0xffffffff) not to be used
class Spline {
public:
  Spline () {}
  vec::fixed<dim> operator () (double const t) const {}
};
template<>
class Spline<~0> {  // specialize the default dimension for runtime use
public:
  Spline (std::size_t const dim) {}
  vec operator () (double const t) const {}
};

可以这样使用:

Spline<5> o5;  // compile time dimensions
Spline<> o0(3); // run time dimensions (don't mention anything in template)

你可以重载它。然而,要实现一个不重复的实现是一个没有通用解决方案的问题,除非您有更多的模板可以做到这一点。