Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to invoke c_str() for std::string variadic template parameters?

I have a method that accepts format string + arguments (right as printf()), however, I'm using variadic templates for this purpose:

template<typename... Args>
static void log(const char* pszFmt, Args&&... args)
{
    doSomething(pszFmt, std::forward<Args>(args)...);
}

Some of args can be std::string instances. Is it possible to make sure that doSomething will never accept std::string, but will always accept const char* instead of each source std::string passed to log()?

In other words, I need a way to forward all the args to doSomething() making all the std::string arguments substituted with what std::string::c_str() returns.

Thanks in advance!

like image 616
Roman Avatar asked Oct 29 '25 07:10

Roman


2 Answers

You could define your own "forwarding" method:

template<typename T>
decltype(auto) myForward(T&& t)
{
    return t;
}

template<>
decltype(auto) myForward(std::string& t)
{
    return t.c_str();
}


template<>
decltype(auto) myForward(std::string&& t)
{
    return t.c_str();
}


template<typename... Args>
static void log(const char* pszFmt, Args&&... args)
{
    doSomething(pszFmt, myForward<Args>(std::forward<Args>(args))...);
}
like image 110
Michael Avatar answered Oct 31 '25 21:10

Michael


Here's an alternative solution. If your logger simply prints each argument and doesn't "store" it, then there's no need to perfect-forward the arguments, a simple pass-by-reference will suffice.

In that case you can simply overload or specialize the printer function for various "printable" types.

template <class T>
decltype(auto) printer(T const& t) {
    return t;
}

inline const char* printer(std::string const& t) {
    return t.c_str();
}

template<typename... Args>
void log(const char* pszFmt, Args const&... args) {
    printf(pszFmt, printer(args)...);
}

int main() {
    std::string str{"xyz"};
    log("%s %s %s\n", "abc", std::string("def"), str);
}

Note: the non-template overload will always be preferred during overload resolution.

like image 31
rustyx Avatar answered Oct 31 '25 20:10

rustyx



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!