2011-04-17 50 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)