【问题标题】:read arguments from variadic template从可变参数模板中读取参数
【发布时间】:2011-04-08 18:24:13
【问题描述】:

我有点困惑如何使用可变参数模板从元组中读取每个参数。

考虑这个函数:

template<class...A> int func(A...args){
int size = sizeof...(A);
.... }

我从主文件中调用它,例如:

func(1,10,100,1000);

现在,我不知道如何扩展 func 的主体,以便能够分别读取每个参数,例如,我可以将参数存储在数组中。

【问题讨论】:

  • 您在上一个问题中遗漏了什么? (stackoverflow.com/questions/3634379/variadic-templates) 你为什么不接受你的问题的答案?
  • 答案应该在链接的线程中(莫蒂,没有投票?)
  • @sami:阅读常见问题解答至少一次...引用它:When you have decided which answer is the most helpful to you, mark it as the accepted answer by clicking on the check box outline to the left of the answer.
  • @sami:这不是重点。您问了 5 个问题,但没有接受 任何个问题的答案。这个 (stackoverflow.com/questions/3626483/…) 出了什么问题?如果您觉得自己无法花 10 秒时间感谢某人花费了一些时间来帮助您,那么这可能不是适合您的网站。

标签: c++ c++11


【解决方案1】:

如果参数有不同的类型,你也可以使用std::common_type&lt;&gt;

template<class ...A> void func(A ...args){
   typedef typename std::common_type<A...>::type common;
   std::array<common, sizeof...(A)> a = {{ args... }};
}

例如,func(std::string("Hello"), "folks") 创建了一个 std::string 数组。

【讨论】:

    【解决方案2】:

    如果参数都是相同的类型,您可以将参数存储在这样的数组中(使用数组的第一个参数的类型):

    template <class T, class ...Args>
    void foo(const T& first, const Args&... args)
    {
        T arr[sizeof...(args) + 1] = { first, args...};
    }
    
    int main()
    {
        foo(1);
        foo(1, 10, 100, 1000);
    }
    

    如果类型不同,我想你可以使用boost::any,但我看不出你将如何在给定模板之外找出哪个项目属于哪种类型(你将如何使用存储的值)。


    编辑: 如果参数都是相同的类型,并且您想将它们存储到 STL 容器中,您可以使用std::initializer_list&lt;T&gt;。比如 Motti 逆向存储值的例子:

    #include <vector>
    #include <iostream>
    #include <iterator>
    
    template <class Iter>
    std::reverse_iterator<Iter> make_reverse_iterator(Iter it)
    {
        return std::reverse_iterator<Iter>(it);
    }
    
    template <class T>
    std::vector<T> reverse(std::initializer_list<T> const & init)
    {
    
        return std::vector<T>(make_reverse_iterator(init.end()), make_reverse_iterator(init.begin()));
    }
    
    int main() {
        auto v = reverse({1, 2, 3, 4});
        for (auto it = v.begin(); it != v.end(); ++it) {
            std::cout << *it << std::endl;
        }
    } 
    

    【讨论】:

    • boost 库是否也支持可变参数模板的 STL 容器?
    • 如果参数不是来自相同的数据类型怎么办?
    • 用于不同类型值的标准“容器”是std::tuple
    【解决方案3】:

    您必须为使用第一个 N(通常是一个)参数的函数提供覆盖。

    void foo() {
       // end condition argument pack is empty
    }
    
    template <class First, class... Rest> 
    void foo(First first, Rest... rest) {
        // Do something with first
        cout << first << endl; 
    
        foo(rest...); // Unpack the arguments for further treatment
    }
    

    当你解压可变参数时,它会找到下一个重载。

    示例:

    foo(42, true, 'a', "hello");
    // Calls foo with First = int, and Rest = { bool, char, char* }
    // foo(42, Rest = {true, 'a', "hello"}); // not the real syntax
    

    然后下一层我们扩展之前的Rest 并得到:

    foo(true, Rest = { 'a', "hello"}); // First = bool
    

    以此类推,直到Rest 不包含任何成员,在这种情况下解包它调用foo()(不带参数的重载)。


    不同类型的存储包

    如果你想存储整个参数包,你可以使用std::tuple

    template <class... Pack>
    void store_pack(Pack... p) {
        std::tuple<Pack...> store( p... );
        // do something with store
    }
    

    然而这似乎没那么有用。

    如果包装是同质的,则存放

    如果包中的所有值都是同一类型,您可以像这样存储它们:

    vector<int> reverse(int i) {
        vector<int> ret;
        ret.push_back(i);
        return ret;
    }
    
    template <class... R>
    vector<int> reverse(int i, R... r) {
        vector<int> ret = reverse(r...);
        ret.push_back(i);
        return ret; 
    }
    
    int main() {
        auto v = reverse(1, 2, 3, 4);
        for_each(v.cbegin(), v.cend(), 
            [](int i ) { 
                std::cout << i << std::endl; 
            }
        );
    }
    

    然而这似乎甚至没有有用。

    【讨论】:

    • @Motti:我明白你的意思。但是我还有两个问题:1-如果要指定数据类型,可以这样调用函数foo吗: foo(42, true, 'a', "hello") 2-我可以在哪里读取值以在解压后将其存储在我想要存储的位置,这是我的主要问题!
    • @sami, 1. 我不确定标准是怎么说的,但 g++ 接受foo&lt;char&gt;(42) 在这种情况下我得到* 而不是42,这意味着它将参数强制为@ 987654335@.
    • @sami, 2. 如果这些类型不同,则不能将它们存储在常规数组中(除非您使用 boost::any 或 Kirill 建议的类似内容)
    • 看来应该先结束条件。
    • @Motti:谢谢。我不知道为什么有 100 多个示例描述如何解包和输出参数,同时没有示例描述如何单独存储每个参数。
    【解决方案4】:

    如果您需要在数组中存储参数,您可以使用boost::any 的数组,如下所示:

    template<typename... A> int func(const A&... args)
    {
      boost::any arr[sizeof...(A)] = { args... };
      return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-01
      • 2021-10-29
      • 2013-09-14
      • 1970-01-01
      • 2013-09-22
      相关资源
      最近更新 更多