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

时间:2011-04-17 20:33:14

标签: c++ templates

假设我有一个这样的对象:

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>,但没有实现所有函数两次。特别是,我必须根据是否存在模板参数来选择所有这些函数的返回类型。

您是否知道如何实现这一目标,特别是考虑清晰可维护的设计? (希望我明确表示,我并不完全确定。)

3 个答案:

答案 0 :(得分:3)

使用简单的traits metastruct并将其专门化。

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的两倍...:/ Lemme认为我是否也可以找到解决方案。
修改:如果您不希望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;
  };
};

并用作

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

答案 1 :(得分:1)

如果我正确理解您的问题,您需要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)

答案 2 :(得分:0)

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