专门针对一种数据类型的参数包

时间:2018-07-17 10:58:46

标签: c++ c++11 c++14 variadic-templates c++17

我有以下代码将传递给函数的所有参数转换为csv:

void Parse(ostream& os)
{
}

template <typename T, typename... Args>
void Parse(ostream& os, T t, Args... args)
{
    os << *t << ',';
    Parse(os, args...);
}

虽然这对于我正在做的所有数据类型都适用,但我希望对char数据类型进行一些特殊处理。如果有一个char参数(例如0),我想将其转换为ascii(48为零),然后将其添加到csv中。我无法在呼叫者位置对其进行修改。如何在参数包中处理它?<​​/ p>

4 个答案:

答案 0 :(得分:3)

template <typename T, typename... Args>
void Parse(ostream& os, T t, Args... args)
{
    if constexpr(std::is_same_v<T, char>)
    {
        os << to_ascii(t) << ',';
    }
    else
    {
        os << *t << ',';     
    }

    Parse(os, args...);
}

答案 1 :(得分:1)

您只需定义一个重载函数(在下面的示例中为details::print())来处理单个数据,然后使用fold expression将它们联接:

namespace details {

    template<typename T>
    void print(std::ostream&os, T const&x)
    { os << x << ','; }   // print any value

    template<typename T>
    void print(std::ostream&os, T*x)
    { print(os,*x); }     // print value pointed to 

    template<typename T>
    void print(std::ostream&os, const T*x)
    { print(os,*x); }     // print value pointed to 

    void print(std::ostream&os, const char*x)
    { os << x << ','; }   // print C-style string

}

template<typename...Args>
void parse(std::ostream&os, const Args& ...args)
{
    (details::print(os,args) , ...);   // fold expression
}

int main()
{
    double x=3.1415;
    parse(std::cout,"fun",42,'d',&x);
}

输出:fun,42,d,3.1415,

您可以通过Jarod的回答方法来消除尾随逗号(尽管您的原始帖子没有抑制它)。

答案 2 :(得分:0)

由于使用递归处理参数包,因此可以添加两个重载

Dafny 2.1.1.10209
stdin.dfy(24,12): Error: member left does not exist in trait Atom
1 resolution/type errors detected in stdin.dfy

并将原始可变参数函数定义更改为

void Parse(ostream& os) {} /* As before. */

void Parse(ostream& os, char *c)
{
    os << handleChar(*c) << ",";
}

template <class T> void Parse(ostream& os, T t)
{
    os << *t << ",";
}

在调用带有两个参数的template <typename T, typename... Args> void Parse(ostream& os, T t, Args... args) { Parse(os, t); Parse(os, args...); } 时,编译器将首选此非模板函数,第二个参数为Parse

答案 3 :(得分:0)

我会将迭代与实际操作分开:

template <typename T>
void Handle(std::ostream& os, const char*& sep, T arg)
{
    os << sep << arg;
    sep = ",";
}

void Handle(std::ostream& os, const char*& sep, char arg)
{
    os << sep << (int)arg;
    sep = ",";
}

template <typename... Args>
void Parse(std::ostream& os, Args... args)
{
    const char* sep = "";
    (Handle(os, sep, args), ...);
}