2010-07-15 62 views
3

不完全確定如何標註此問題或搜索什麼,如果這與另一個問題相同,請關閉並重定向到相應的問題。整數模板參數指定參數個數的類方法

假設

template<typename Type, int Size> class vector 
{ 
    Type data[Size]; 
} 

是否有可能更換一個構造函數,採用的參數大小數模板特喜歡這個

template<typename Type> class vector3<Type,3> 
{ 
    Type data[3]; 
    public: 
    vector3(Type, Type, Type); 
} 

的東西在非專業模板類?像一個「可變參數構造函數」,它產生一個構造函數,其大小數量爲Type類型的參數。

涉及C++ 0x功能的解決方案很好。

回答

5

在C++ 0x你有template typedef終於可用!

免責聲明:什麼也沒有編...

維基百科的文章:

template< typename second> 
using TypedefName = SomeType<OtherType, second, 5>; 

而你的情況會產生

template <class Type> 
using vector3 = vector<Type, 3>; 

我不能告訴你如何很多我渴望這個;)

但它不能解決參數問題。如前所述,你可以嘗試在這裏使用可變參數模板,但是我不確定在這種情況下它們的應用。正常的使用是遞歸方法,你需要在中間放一個static_assert

編輯考慮到意見。

template <class Type, size_t Size> 
class vector 
{ 
public: 
    template <class... Args> 
    vector(Args... args): data({args...}) 
    { 
    // Necessary only if you wish to ensure that the exact number of args 
    // is passed, otherwise there could be less than requested 
    BOOST_MPL_ASSERT_RELATION(sizeof...(Args), ==, Size); 
    } 

private: 
    T data[Size]; 
}; 

已有的另一種可能性是將預處理器生成與boost::enable_if相結合。

template <class Type, size_t Size> 
class vector 
{ 
public: 
    vector(Type a0, typename boost::enable_if_c< Size == 1 >::type* = 0); 
    vector(Type a0, Type a1, typename boost::enable_if_c< Size == 2 >::type* = 0); 
    // ... 
}; 

使用Boost.Preprocessor進行生成使得這更容易。

BOOST_PP_REPEAT(MAX_COUNT, CONSTRUCTOR_MACRO, ~); 

// where MAX_COUNT is defined to the maximum size you wish 
// and CONSTRUCTOR_MACRO actually generates the constructor 

#define CONSTRUCTOR_MACRO(z, n, data)        \ 
    vector(               \ 
    BOOST_PP_ENUM_PARAMS(n, Type a),        \ 
    typename boost::enable_if_c< Size == n >::type* = 0   \ 
); 

構造函數的實現留給讀者練習。這是另一個電話BOOST_PP_REPEAT。正如你所看到的,它很快變得醜陋,所以如果你可以使用可變模板版本,你會變得更好。

+0

sizeof ...(Args)的模板參數個數? – Tomek 2010-07-15 17:25:11

+0

也許,我從來沒有需要它,我找不到任何參考... – 2010-07-15 17:35:33

+1

通過使用初始化程序列表:'data({args ...})'擺脫您的'init'函數 – phlipsy 2010-07-15 20:06:22

2

是否有可能取代一個構造函數,採用的參數大小數模板特喜歡這個

不是沒有一噸的重複,機械的代碼,並且最大尺寸將由數量限制你重複自己的時間。例如:boost::tuple(它可能正是你想要的功能)。

在C++ 0x這將不會是一個問題多虧了variadic templates

3

有進一步的解決問題的方法:在初始化列表中

template<typename T, unsigned int N> 
struct vector { 
    T data[N]; 

    template<typename... Args> 
    vector(Args... args) : data({args...}) { } 
}; 

但是參數的個數僅需要小於或等於比N使用可變參數模板參數和它們的類型只需要可以轉換成T

+0

適用於我也是我想我的措辭聽起來像「確切」是一個要求。我會編輯說至少。在這種情況下,構造函數應該默認構造其他成員(如果有的話),對嗎? – bpw1621 2010-07-16 00:40:03

+0

@ bpw1621:對。但是正如卡斯平告訴你應該考慮使用'array'也提供一個固定長度的數組。但是,如果您需要爲您的類型重載算術運算,則您將被迫在內部'array'中理想地編寫自己的新類。 – phlipsy 2010-07-16 13:20:31

+0

哈哈,我在看到這個答案之前寫了很多代碼來做到這一點。 :P – CodeRarity 2013-02-14 02:55:04

2

首先您應該考慮使用std::array。它不符合你的所有要求,但它足夠接近,如果差異無關緊要,你可以節省很多工作。問題是這樣的廉價版本將具有構造接受2個參數,以及3

template< typename T> 
using Vector3 = std::array<T,3>; 

Vector3 v1{1,2,3}; 
Vector3 v2{1,2}; // it sounds like you want to disallow this case. 

否則,你可以創建一個充當很像std::array,除了用更挑剔的構造函數的自定義類。

template<typename T, std::size_t SIZE> 
class Vector 
{ 
public: 
    template< typename ... Args > 
    Vector(Args ... args) : 
     data({args...}) 
    { 
     static_assert(sizeof...(Args) == SIZE, 
        "Incorrect number of arguments passed to Vector constructor"); 
    } 
    /* lots of extra code here to add std::array -like methods */ 
private: 
    // could use std::array here as well. 
    T data[3]; 
}; 

template< typename T > 
using Vector3 = Vector<T,3>; 

Vector3 v1(1,2,3); 
Vector3 v2(1,2); // error at compile time. 
+0

好主意,使用static_assert來保證參數的確切數量。有關它們類型的任何想法?他們只能轉換爲'T' ... – phlipsy 2010-07-16 13:15:33

+0

我可以使用'std :: same_type '添加另一個'static_assert'來強制執行正確的類型,但我認爲這會自我挫敗。我想'Vector3 vi(11,12,13)'只是工作。如果我需要確切類型,我必須將無符號說明符添加到整數文字。 – 2010-07-16 13:53:31

相關問題