2011-04-17 69 views
3

假设我有一个这样的对象:动态数据类型选择

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

使用一个简单的性状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 ......的两倍大小:/让我想我是否也能找到解决方案。
编辑:如果你不想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; 
+0

不应该是'typename Spline :: fixed <10> :: type fixed_10_spline;'? – 2011-04-18 05:03:50

+0

谢谢。我每天都会学到新的东西 - 这次你做到了;) – Thilo 2011-04-18 08:01:57

0

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

+1

是否有可能在返回类型重载? – 2011-04-17 20:53:45

1

如果我正确理解你的问题,你想要一个struct编译时间使用和运行时使用以及最好是相同的名称。在我看来,你可以声明classtemplate,然后专门化一个它的实例(比如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)