可以对可变参数模板的折叠表达式进行分箱,并使用参数列表到向量的转换吗?

问题描述 投票:0回答:1

当 C++ 17 中引入折叠表达式时,我学会了如何使用以下形式为可变参数模板编写代码:

args OP ...

等等

现在,通常在编程中,当我们有很长的参数列表时,我们使用数组或向量,在它们上我们可以使用“for”或“while”循环进行迭代。

我刚刚了解到 C++ 允许将可变参数模板的打包参数列表转换为简单向量,如下所示:

template<class ... Args>
void foo()
{
   using arg_type = typename std::common_type_t<Args...>;

   std::vector<arg_type> arr = {args...};
}

这让我得出结论,现在,对于任何可变参数模板,我可以使用向量容器自由地迭代参数列表,而不是使用折叠表达式编写奇怪的代码。

此外,AFAIU,折叠表达式技术允许在一个参数和剩余的折叠表达式上仅调用一个二元运算符,这是非常有限的。

我的意思是,现在我完全可以自由地对参数做任何我想做的事情,而不仅仅是对它们调用一些二元运算符?

例如,我可以按如下方式打印我的参数:

    template<class ... Args>
    void printSorted(const Args& ... args)
    {
        using arg_type = typename std::common_type_t<Args...>;
        
        vector<arg_type> arg_vec = { args ... };
        
        sort(arg_vec.begin(), arg_vec.end());
        
        for(const auto& a : arg_vec)
        {
            cout << a << " ";
        }
        cout << endl;
    }

printSorted(3, 1, 5, 3, 7, 8, 2, 0);

我怀疑我能用折叠表达式做到这一点(即使我能做到,它看起来也会很糟糕)。

现在,对于已知的模板类型参数,它甚至更简单:

template<bool ... args>
int read_binary_value()
{
    const vector<bool> vals = { args ... };
    
    int res = 0;
    
    for(int i = 0; i < vals.size(); ++i)
    {
        res <<= 1;
        res += vals[i];
    }
    
    return res;
}

cout << read_binary_value<1, 0, 1>() << endl;

那么我对吗,折叠表达式技术现在可以被合并并被更直观和可读的参数数组迭代技术所取代?

c++ templates variadic-templates template-meta-programming fold-expression
1个回答
0
投票

那么我对吗,折叠表达式技术现在可以被合并并被更直观和可读的参数数组迭代技术所取代?

不;您展示的所有用例仅适用于“同质包”。 这些包中的所有参数都具有相同的类型,或者可以转换为相同的类型。

using arg_type = typename std::common_type_t<Args...>;
std::vector<arg_type> arr = {args...};

如果没有一个所有参数都可以转换成的通用类型,这显然会失败。 例如,如果

Args
int*
float*

折叠表达式更加强大,因为即使没有通用类型它们也能工作,例如:

(std::cout << ... << args);

args
可以是字符串、整数、指针等,全部合二为一。

如果您有同构包,通常根本不需要可变参数模板,只需使用

std::array
std::initializer_list

© www.soinside.com 2019 - 2024. All rights reserved.