繁体   English   中英

c ++ 11递归可变参数模板

[英]c++11 recursive variadic templates

我试图了解递归可变参数模板的工作原理。

#include <iostream>

template<typename T>
static inline void WriteLog(T&& msg) {
    std::wcout << std::forward<T>(msg);
}

template<typename T, typename... Ts>
static void WriteLog(T&& msg, Ts&&... Vals) {
    WriteLog(std::forward<T>(msg));
    WriteLog(std::forward<Ts>(Vals)...);
    std::wcout << "\n**End**";
}

int main() {
    WriteLog("apple, ", "orange, ", "mango");
}

输出:

apple, orange, mango
**End**
**End**

我预计只有一个**End** 为什么要打印两次?

调用树:

 WriteLog("apple, ", "orange, ", "mango");
       ->WriteLog("apple, ");
            -> std::wcout << "apple, ";
       ->WriteLog( "orange, ", "mango");
            ->WriteLog("orange, ");
                 -> std::wcout << "orange, ";
            ->WriteLog( "mango");
                 -> std::wcout << "mango";
            ->std::wcout << "\n**End**";
       ->std::wcout << "\n**End**";

当递归调用WriteLog(std::forward<Ts>(Vals)...); 完成后,它必须执行下一个语句。 此功能被调用两次(一次用于"apple" ,一次用于"orange" ),因此写入两次"**End**"打印输出。

"mango"的最后一次递归调用直接进入第一次重载,因为包中只剩下一个参数。

**End**打印用于打电话

  • WriteLog("apple, ", "orange, ", "mango"); main
  • WriteLog("orange, ", "mango"); (在WriteLog(std::forward<Ts>(Vals)...);使用WriteLog(std::forward<Ts>(Vals)...); WriteLog("apple, ", "orange, ", "mango")

我会老实说你,我已经写了4年的c ++ 11模板代码了,我仍然无法记住如何匹配空参数包......

这个小技巧完全避免了递归模板扩展:(编辑:重写以支持零参数和自动逗号分隔符插入)

#include <iostream>

namespace detail {
    struct writer
    {
        template<class T>
        void operator()(const T& t) {
            if (_first) {
                _first = false;
            }
            else {
                std::cout << ", ";
            }
            std::cout << t;
        }

    private:
        bool _first = true;
    };

    // non-template overload to catch no-parameter case
    void do_write(writer&&)
    {

    }

    // general case. Note w is passed by r-value reference
    // to allow the caller to construct it in-place        
    template<typename T, typename...Ts>
    void do_write(writer&& w, const T& t, Ts&&...ts)
    {
        w(t);
        do_write(std::forward<writer>(w), std::forward<Ts>(ts)...);
    }


}

// method 1 - no recursion
template<typename... Ts>
void WriteLog1(Ts&&... Vals) {
    // expand one call for each parameter
    // use comma operator to ensure expression result is an int
    detail::writer write;

    using expander = int[];
    expander { 0, (write(std::forward<Ts>(Vals)), 0)... };

    // write the final linefeed
    std::cout << std::endl;
}

// method 2 - recursion

template<typename...Ts>
void WriteLog2(Ts&&...ts)
{
    detail::do_write(detail::writer(), std::forward<Ts>(ts)...);
    std::cout << std::endl;
}

int main() {
    WriteLog1("apple", "orange", "mango");
    WriteLog1("apple", "orange");
    WriteLog1("apple");
    WriteLog1("apple", 1.0, "orange", 1L, "mango", 2.6f);
    WriteLog1(); // test pathalogical case

    WriteLog2("apple", "orange", "mango");
    WriteLog2("apple", "orange");
    WriteLog2("apple");
    WriteLog2("apple", 1.0, "orange", 1L, "mango", 2.6f);
    WriteLog2(); // test pathalogical case
    return 0;
}

输出:

apple, orange, mango                                                                                                                                             
apple, orange                                                                                                                                                    
apple                                                                                                                                                            
apple, 1, orange, 1, mango, 2.6                                                                                                                                  

apple, orange, mango                                                                                                                                             
apple, orange                                                                                                                                                    
apple                                                                                                                                                            
apple, 1, orange, 1, mango, 2.6

>                                                                                                                                  

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM