簡體   English   中英

使用模板variadic函數將多個參數傳遞給另一個函數

[英]pass multiple arguments to another function using template variadic function

讓我們考慮以下功能:

static void Print(const Type& type, const std::string& message, const std::string& variable) {
    Log(type, message + ": " + variable);
}

我希望它傳遞任意數量的變量(我的意思是std::string & variable - 它保存一個變量名),然后通過Log()函數一起發送它們,因此我考慮使用模板可變參數函數(重載的Print() )。 我這樣定義它:

template <typename Arg, typename ...Args)
static void Print(const Type& type, const std::string& message,
                  const Arg& arg, const Args&... args);

接着:

Print(type, message, args...);
Log(type, message + ": " + arg);

只是一個想法,這很可能會像這樣:

  • args...將被傳遞, Print()函數將被遞歸調用,直到沒有參數為止,
  • 但同時,將調用Log()函數,它基本上每次都會記錄它。

我需要做的是以某種方式記住arg值,但它需要使用另一個參數調用Print() ,我真的不喜歡這個想法。 你還有其他線索嗎?

根據所需的格式,您可以使用折疊表達式:

template<class... Args>
void Print(const Type& type, const std::string& message, const Args&... arg)
{
    std::stringstream strstr;
    strstr << message << ": "; // Or your prefix computation, whatever you want.

    ((strstr << arg << ", "), ...);

    std::string toLog = strstr.str();
    // Remove last separator characters.
    toLog.erase(toLog.end() - 2, toLog.end());
    Log(type, strstr.str());
}

演示

在我看來,Max Langhof的解決方案簡單而優雅。

不幸的是,它使用的模板折疊僅從C ++ 17開始提供。

我提出了一個C ++ 11 / C ++ 14版本,而不是模板折疊,它使用了未使用數組初始化的舊技巧

template <typename ... Args>
void Print (Type const & type, std::string const & message,
            Args const & ... arg)
 {
   using unused = int[];

   std::stringstream strstr;

   strstr << message << ": ";

   (void)unused { 0, (strstr << arg << ", ", 0)... };

    std::string toLog = strstr.str();

    // Remove last separator characters.
    toLog.erase(toLog.end() - 2, toLog.end());
    Log(type, strstr.str());
 }

我簡化了你的例子,所以假設我正確地理解你想做什么,你可以做以下兩個解決方案之一,如果你的編譯器不支持@Max Langhof建議的C ++ 17折疊。

它們都可以在任何支持operator +的類型上運行,但是如果你的concat函數是其他東西,它們很容易修改。

選項1,遞歸解包:

template <typename Arg>
static void Print(const Arg& message, const Arg& arg1)
{
    Log(message + ": " + arg1);
}

template <typename Arg, typename... Args>
static void Print(const Arg& message, const Arg& arg1, const Arg& arg2, const Args&... variables)
{
    Print(message, arg1 + ", " + arg2, variables...);
}

選項2,解壓縮到std:vector:

template <typename Arg, typename... Args>
static void Print2(const Arg& message, const Arg& arg1, const Args&... variables)
{
    std::vector<Arg> args = { variables... };
    Arg result = std::accumulate(args.begin(), args.end(), arg1, [](const Arg& a, const Arg& b) {
        return a + ", " + b;});
    Log(message + ": " + result);
}

請注意,此版本將在std :: vector中創建參數的副本,而不像其他解決方案那樣。

這兩個示例都可以按以下方式使用:

static void Log(const std::string& m)
{
    std::cout << m << std::endl;
}

int main()
{
    std::string msg = "MyMessage1";
    std::string var1 = "Var1";
    std::string var2 = "Var2";
    std::string var3 = "Var3";
    std::string var4 = "Var4";
    std::string var5 = "Var5";

    Print(msg, var1);
    Print(msg, var1, var2);
    Print(msg, var1, var2, var3);
    Print(msg, var1, var2, var3, var4);
    Print(msg, var1, var2, var3, var4, var5);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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