Search code examples
c++c++14fmt

Formatting type by fallback to pointer with fmt library


I am try using

fmt::format("Expected : '{}' vs. '{}'", getDataOrPointer(rA), getDataOrPointer(rB));

where getDataOrPointer should return a void pointer (which can always be formatted) or the default value when a formatter exists:

//! Return the type if a `fmt::formatter` exists.
template<typename T,
         typename std::enable_if_t<hasFormatter<std::decay<T>, char>>* = 0>
decltype(auto) getDataOrPointer(const T& rData)
{
    return rData;
}

//! Return a void-Pointer if no `fmt::formatter` exists.
template<typename T,
         typename std::enable_if_t<!hasFormatter<std::decay<T>, char>>* = 0>
const void* getDataOrPointer(const T& rData)
{
    return static_cast<const void*>(&rData);
}

I dont know how to write: hasFormatter<T,char> to check if it can be formatted or not by the fmt library?. I want this fallback only locally not always.


Solution

  • You can use fmt::has_formatter, quoting https://github.com/fmtlib/fmt/issues/1369:

    has_formatter<T, Context> tells you that type T has a formatter specialization for Context (context basically specifies character and output iterator types) and it can be used with SFINAE. Example: https://godbolt.org/z/pCD14x. The main caveat is that types with implicit conversion can be formattable but not have a formatter specialization.