Search code examples
c++11variadic-templates

How to form a string using variadic templates without recursion in c++ 11


template <typename ...Args>
void logImpl(tloglevel level, Args&& ...args)
{
    ostringstream stream;
    (stream << ... << std::forward<Args>(args)) << '\n';
    syslog(level, stream.str());
}

func A()
{
int a =10;
std::string b = "test";
logImpl(LOG_INFO, "printing",a,b);
}

func B()
{
unsigned long t = 6700;
logImpl(LOG_INFO, t);
}

I understand that we can achieve it using variadic templates. But is it possible to do it without recursion? fold expression is not an option as only c++ 11 is supported. Please let me know if anyone else has better idea using variadic templates without recursion or fold expression. I want to do it in c++11.


Solution

  • You don't need to use recursion to make this work.

    You can create fake array with expanding parameters pack when filling it:

    template<class ... Args>
    std::string makeString(Args...args){
        std::string s;
        int temp[] = { (s += toString(args),0)... }; // concatenation
        static_cast<void>(temp);
        return s;
    }
    

    for toString you provide overloads for handling all types you want.

    For example:

    template<class T>
    std::string toString(T t){
        return std::to_string(t);   // for numbers 
    }
    
    std::string toString(const std::string& str){
        return str;
    }
    
    std::string toString(const char* str){
        return str;
    }
    

    Full demo


    Hmm, you don't even use toString, version with ostringstream is:

    template<class ... Args>
    std::string makeString(Args&&...args){
        std::ostringstream os;
        int temp[] = { ((os << std::forward<Args>(args)),0)... };
        static_cast<void>(temp);
        return os.str();
    }