Search code examples
c++c++20type-traitsc++-concepts

How to check that a type is 'formattable' using type traits / concepts?


I would like to check if a certain type can be used with std::format.

This is my naive attempt:

template<typename Object>
concept formattable = requires(const Object & obj)
{
    std::format("{}", obj);
};

But this does not work. It basically returns true for all types. Even those that can't be used with std::format.

static_assert(!formattable<std::vector<int>>); // should return false

Why doesn't it work?


Solution

  • Update:

    With the introduction of Formatting Ranges, there is already a concept in C++23 dedicated to testing whether a type is formattable, namely std::formattable.


    Since std::format is not a constrained function, the expression std::format("{}", obj) is always well-formed. You might want to do

    #include <format>
        
    template<typename T>
    concept formattable = requires (T& v, std::format_context ctx) {
      std::formatter<std::remove_cvref_t<T>>().format(v, ctx);
    };
    

    which mainly based on the constraints of the basic_format_arg's constructor in [format.arg].

    Demo