[英]Function overloading inside overloaded function
我正在使用C++14
(而且還很新)。 我有3個重載函數func
,其中另一個重載函數do_something
取決於其父函數( func
)被調用。
int func(int a) {
bar(a);
foo();
}
int func(int a, float b) {
bar(a);
do_something(b);
foo();
}
int func(int a, float b, char c) {
bar(a);
do_something(b, c);
foo();
}
我看到func
中的功能幾乎相同,除了調用了哪個版本的do_something
。 有什么辦法可以使這個泛型並將所有func
組合在一起?
首先,將func
接受參數包的模板。 int a
參數,對bar
的調用和對foo
的調用始終存在,因此很簡單。 現在,為do_something
添加一個占位符。
template <class ...Args>
int func(int a, Args&&... other)
{
bar(a);
// somehow call do_something and do the right thing
foo();
return 0;
}
您要像以前一樣實例化並調用上述模板:
func(42);
func(42, 1.f);
func(42, 1.f, 'A');
現在,讓我們處理對do_something
的調用。 如果您只是將其添加到新func
模板的中間, func
do_something(std::forward<Args>(other)...);
這拒絕為func(42)
編譯,即只有一個參數的情況。 因此,我們需要為此提供特殊情況。 在do_something
另一個間接級別中實現此目標的一種方法:
// No additional argument case, does nothing:
void do_something_wrapper() {}
// The other two cases
template <class ...Args>
void do_something_wrapper(Args&&... args)
{
do_something(std::forward<Args>(args)...);
}
現在, func
函數模板中的占位符應為:
do_something_wrapper(std::forward<Args>(other)...);
第一步將使用可變參數模板來完成您要轉發到do_something
:
template<class ... Args>
int func(int a, Args... args)
{
bar(a);
do_something(std::forward<Args>(args)...)
foo();
}
但是現在您已經失去了func的參數類型。 因此,如果這是一個問題,您將必須找到一種方法來再次測試它們。
盡管我本人可能會回答generic_opto_guy的答案,但他是正確的指出您會丟失界面中的類型。 根據您的情況,您可能需要保留此設置。
在這種情況下,您可以輕松地將其重新整理為類似於以下內容的內容:
namespace details {
template<class ... Args>
int func_impl(int a, Args &&... args)
{
bar(a);
do_something(std::forward<Args>(args)...)
foo();
}
}
int func(int a) { return details::func_impl(a); }
int func(int a, float b) { return details::func_impl(a, b); }
int func(int a, float b, char c) { return details::func_impl(a, b, c); }
請注意,已對實現進行了調整,以使用完美轉發 。 盡管在這種特定情況下不是必需的,但在將來可能遇到的轉發情況下,它通常很有用。
同樣,除非您絕對需要提供一個清晰的客戶端代碼接口,否則我將只使用第一個實現。
其他答案是所問問題的通用回答,但是,如果您有幾個可用的c
備用值,則可以這樣編寫:
int func(int a) {
func(a, 0.0,'\001');
}
int func(int a, float b, char c = '\002') {
bar(a);
switch (c) {
case '\001':
break; // func(a)
case '\002':
do_something(b): // func(a, b)
break;
default:
do_something(b, c); // func(a, b, c)
break;
}
foo();
}
根據應用程序,這可能會更簡單。
玩太晚了嗎?
您標記了C ++ 14,但是,如果可以使用C ++ 17,則可以使用if constexpr
因此
template <typename ... Ts>
int func (int a, Ts && ... ts)
{
bar(a);
if constexpr ( sizeof...(Ts) > 0u )
do_something(std::forward<Ts>(ts)...);
foo();
// and remember to return something of int
}
在C ++ 14中,您必須在某處復制某些內容。
或者您編寫兩個func()
int func (int a)
{
bar(a);
foo();
// and remember to return something of int
}
template <typename ... Ts>
int func (int a, Ts && ... ts)
{
bar(a);
do_something(std::forward<Ts>(ts)...);
foo();
// and remember to return something of int
}
或添加無參數do_something()
void do_something ()
{ }
或者,根據lubgr的建議,您可以通過包裝器調用do_something()
(創建一個特殊的無參數包裝器)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.