1

我目前正在清理一個充滿功能模板的API,並且強烈要求編寫下面的代碼。需要默認參數值的模板函數的首選設計是什麼?

template <typename T, typename U, typename V> 
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0); 

當我調用這個模板時,我想這樣做如下。

std::string text("hello"); 
doWork(100, 20.0, &text); 
doWork('a', text);   // oops! 
doWork<char, std::string, void>('a', text); // to verbose! 

不幸的是,由於編譯器無法推斷出可選參數的類型,所以第二次調用不能編譯。這是不幸的,因爲我真的不在乎參數類型是什麼,而是它的值是NULL。另外,我想避免第三次調用的路由,因爲它妨礙了可讀性。

這使我試圖使模板參數V有一個默認類型,這也不起作用,因爲您不能將默認類型應用於函數模板參數(至少使用VC++ 9.0)。

template <typename T, typename U, typename V = void> // oops! 
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0); 

我唯一的選擇是引入近朱者赤模板實參VdoWork過載。

template <typename T, typename U> 
void doWork(const T& arg1, const U& arg2) 
{ 
    doWork(arg1, arg2, 0); 
} 

template <typename T, typename U, typename V> 
void doWork(const T& arg1, const U& arg2, V* optionalArg); 

這是解決此問題的最佳方法嗎?我看到的唯一缺點是,如果函數模板包含許多具有合適默認值的參數,我可能會引入許多簡單的轉發函數。

回答

5

我認爲你的轉發功能是一個完美的解決方案,雖然在你的解決方案中,你不需要明確指定模板參數嗎? (0是一個整數常量,可以轉換爲任何V*類型。)還有doWorddoWork

作爲一般規則,儘量避免可選參數,他們沒有很強的回報。

可能更容易迫使你的客戶端功能,只是增加一個, (void*)0如果appriopriate不是增加多少額外的機制,同時支持兩個參數和模板的三個參數的版本。不過,這取決於預期的用途。

+0

是的,你是對的。應在轉發功能中指定'0'的類型。 (FR) – 2009-10-12 17:38:58

0

一種可能性是重新排序模板參數,所以可選的一個首先來。

template <typename V, typename T, typename U> 
void doWork(const T& arg1, const U& arg2, V* optionalArg = 0); 

doWork<void>('a', text); 

轉發看起來也不錯。

但它似乎默認參數和模板不匹配,但。

2

從客戶端代碼的角度來看,如果它沒有第三個參數,爲什麼需要發明一個?

所以,如果你的目標的實用性和可讀性,我同意你的包裝方法:它非常有意義,並且寫的包裝器,負責必要的第三個參數的一個體面的價值。

最重要的是,如果需要,它可以對不同的專業化使用不同的默認值。

+1

ISTR Francis Glassborow曾經說過,儘管超載和(內聯)轉發,首先發明瞭默認函數參數的原因是爲了防止構造函數無法轉發給每個構造函數的問題導致的代碼重複其他。所以,除了構造函數之外,它是不必要的。 (請注意,在C++ 1x中,構造函數將能夠相互轉發。) – sbi 2009-10-11 20:22:45