Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How can I wrap std::format() with my own template function?

Note: this question uses C++20, and I’m using Visual Studio 2022 (v17.2.2).

I would like to create a template function wrapper to allow me to use std::format style logging. The wrapper function will eventually do some other non-format related stuff that is not important here.

Refer to the code below. Note that Log1() works fine, but feels clunky to use. Log2() is ok, but using std::vformat() loses compile-time checking of log format strings.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

What I really want to do is Log3(). Problem is that Visual Studio (v17.2.2) doesn’t like this.

Is there any way I can get this to work (without macros)?

#include <iostream>
#include <format>
#include <string_view>
 
// works fine:  usage is clunky
auto Log1(std::string_view sv)
{
    std::cout << sv;
}
 
// works, but fmt string is checked at runtime - not compile time
template<typename... Args>
auto Log2(std::string_view fmt, Args&&... args)
{
    std::cout << std::vformat(fmt, std::make_format_args(args...));
}
 
// this doesn't work
template<typename... Args>
auto Log3(std::string_view fmt, Args&&... args)
{
    std::cout << std::format(fmt, std::forward<Args>(args)...);
}
 
int main()
{
    Log1(std::format("Hello, {}\n", "world!")); // ok - clunky
    Log2("Hello, {}\n", "world!");              // ok - no compile time checking of fmt string
    Log2("Hello, {:s}\n", 42);                  // ok - throws at runtime
    Log3("Hello, {}\n", "world!");              // ERROR:  doesn't compile
    return 0;
}

>Solution :

You need P2508 (my paper) to land, which exposes the currently exposition-only type std::basic-format-string<charT, Args...>, which will allow you to write:

template<typename... Args>
auto Log3(std::format_string<Args...> fmt, Args&&... args)

Until then, you can just be naughty and use the MSVC implementation’s internal helper for this, with understanding that they can rename this type at will at any point.

template<typename... Args>
auto Log3(std::_Fmt_string<Args...> fmt, Args&&... args) 
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading