簡體   English   中英

重載函數內部的函數重載

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM