Home > Back-end >  build a const char * quickly in c
build a const char * quickly in c

Time:12-04

Suppose I have a log function like this:

void myLog(const char* msg); 

The above assumption can't be changed.

then how can I call it easily in c ; usually I write the code like this:

stringstream ss; 
ss << "name : " << name << " age " << age;
mylog(ss.str().c_str());

can I can reduce the 3 lines to 1 line in c somehow?

thanks!

CodePudding user response:

If you use C 20, you should be able to use std::format.

So your code would look like this:

myLog(std::format("name: {} age: {}", name, age).c_str());

CodePudding user response:

Yes, you can stream into a temporary std::stringstream

myLog((std::stringstream{} << "name : " << name << " age " << age).str().c_str());

See it on coliru

CodePudding user response:

Yes you can, if you are willing to put some code in a seperate header file :

#include <string>
#include <sstream>
#include <iostream>
#include <type_traits>

// given
void myLog(const char* msg)
{
    std::cout << msg << "\n";
}

// this goes into a header file
namespace details
{

    // this function is called with a variable number of arguments
    // by splitting the template into a value_t and a variadic part
    // we basically pick out only the first argument 
    template<typename value_t, typename... args_t>
    void stream_to_os(std::stringstream& os, const value_t& value, args_t&&... args)
    {
        // pick out the first argument and stream it to the stringstream
        os << value;

        // then check (at compile time!) if there are any more arguments to stream
        // if so recurse into this function. Rince and repeat.
        if constexpr (sizeof...(args_t) > 0)
        {
            stream_to_os(os, std::forward<args_t>(args)...);
        }
    }
}

// make use of the fact that you can overload existing functions
// if a const char* is passed then still the original log function will be selected
// otherwise this template function is considered.
template<typename... args_t>
void myLog(args_t&&... args)
{
    // create the stream once
    std::stringstream os;

    // then stream the variadic arguments to the stringstream
    details::stream_to_os(os, std::forward<args_t>(args)...);

    // and now call the original myLog function
    myLog(os.str().c_str());
}

//--------------------------------------------------------
// add an include to the header file with the stuff above
// and you can log like this:

int main()
{
    const char* name{ "John Doe" };
    unsigned int age{ 42u };

    myLog("name = ", name, ", age = ", age);

    return 0;
}

CodePudding user response:

You can use std::to_string and addition operator instead of the string stream, but that limits you to conversion of built in types (or other types with this function implemented for)

mylog(("name:"   name   " age:"   std::to_string(age)).c_str());
  •  Tags:  
  • c
  • Related