假设我有一个这样的对象:
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
}
(对于那些疑惑的人来说,vec
和vec::fixed
是由犰狳线性代数库定义的对象)。现在我希望两个版本并行生成,因此能够在编译时和运行时选择维度。简而言之,我想创建vec::fixed<dim>
等同于Spline::fixed<dim>
,但没有实现所有函数两次。特别是,我必须根据是否存在模板参数来选择所有这些函数的返回类型。
您是否知道如何实现这一目标,特别是考虑清晰可维护的设计? (希望我明确表示,我并不完全确定。)
答案 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)
你可以超载它。然而,制作一个非重复的实现是一个没有通用解决方案的问题,除非你有更多的模板魔术可以做到这一点。