2016-09-21 98 views
10

我有一個模板函數,它接受可變數量的參數。既然你不能強制參數是某種類型,我想至少強制參數的數目不要高於編譯時確定的數目(例如10)。限制可變參數模板參數包中參數的數量

如果帶有參數包的模板函數的參數數量高於編譯時間確定值,編譯器是否可以提供錯誤?

template <class ...Args> 
void setRequestArguments(const Args&... args) 
{ 
    const std::vector<QGenericArgument> vec = { args... }; 
    qDebug() << sizeof...(args); 
    // Do stuff... 
    // for (unsigned i = 0; i < vec.size(); ++i) { 
    //  qDebug() << vec[i].name(); 
    // } 
} 

我想使用它的是一種用於在QMetaObject::invokeMethod包裝函數的所有參數的通用容器。

+1

可以將參數限制爲某種類型。你想對此做出答案嗎?你是否要求參數完全是'T'還是可以轉換爲'T'的東西? – bolov

+0

@bolov是的,請,這將是非常有用的!我會+1 –

+1

我用這個創建了一個新帖子:http://stackoverflow.com/questions/39659127/restrict-variadic-template-arguments/39659128#39659128 – bolov

回答

20

爲了使功能不可調用的時候有太多的參數,可以約束與SFINAE功能。這樣,如果有另一個接受更多參數的重載,編譯器將能夠選擇正確的重載。

簡單std::enable_if與條件就足夠了:

template <class ...Args, std::enable_if_t<(sizeof...(Args) <= 10)>* = nullptr> 
void setRequestArguments(Args&&... args) 
{ 
    const std::vector<QGenericArgument> vec = { std::forward<Args>(args)... }; 
} 

出於可讀性起見,你可以把約束在尾隨返回類型的函數:

template <class ...Args> 
auto setRequestArguments(Args&&... args) -> std::enable_if_t<(sizeof...(args) <= 10)> 
{ 
    const std::vector<QGenericArgument> vec = { std::forward<Args>(args)... }; 
} 

編輯:我添加了轉發引用而不是const引用,因爲它可以加速程序並且對非可複製類型更友好。

+3

這真的是一個有趣的方式使用SFINAE :) – Rakete1111

14

如果帶有參數包的模板函數的參數數量超過編譯時間確定值,編譯器是否可以給出錯誤?

是,使用static_assert

template <class ...Args> 
void setRequestArguments(const Args&... args) 
{ 
    static_assert(sizeof...(args) <= 10, "You can't have more than 10 arguments!"); 
    //Stuff... 
}