最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

templates - How to determine if a Type supports printing or formatting using C++ standard lib? - Stack Overflow

programmeradmin3浏览0评论

I would like to know if there is built-in checkers in std which checks if a type is printable via operator<< or if it is formattable via std::format.

I tried to search it and could not find built-in checker to check if operator<< can be called on a type. I only found std::formattable<T> and could not figure out how to use it.

I want to use built-in type traits and concepts from std, I do not want to create my own utility.

What I would like to be able to do is:

template<typename DATA_T>
struct std::formatter<MyClass<DATA_T>> : std::formatter<std::string>
{
    static auto format(const MyClass<DATA_T>& my_class, std::format_context& ctx)
    {
        std::string result = std::format("Name: {}\n", my_class.name());

        // Check if the data it holds printable or formattable and add it.
        // Should be replaced with correct usage
        if constexpr (std::formattable<DATA_T>) 
        {
            result += std::format("Data: {}", my_class.data());
        }
        // Should be replaced with correct std functionality
        else if constexpr (std::ostreambale<DATA_T>) 
        {
            std::ostringstream oss;
            oss << my_class.data();
            result += "Data: ";
            result += oss.str();
        }

        result += std::format("\nLocation: {}", my_class.location());

        return std::format_to(ctx.out(), "{}", result);
    }
};

I would like to know if there is built-in checkers in std which checks if a type is printable via operator<< or if it is formattable via std::format.

I tried to search it and could not find built-in checker to check if operator<< can be called on a type. I only found std::formattable<T> and could not figure out how to use it.

I want to use built-in type traits and concepts from std, I do not want to create my own utility.

What I would like to be able to do is:

template<typename DATA_T>
struct std::formatter<MyClass<DATA_T>> : std::formatter<std::string>
{
    static auto format(const MyClass<DATA_T>& my_class, std::format_context& ctx)
    {
        std::string result = std::format("Name: {}\n", my_class.name());

        // Check if the data it holds printable or formattable and add it.
        // Should be replaced with correct usage
        if constexpr (std::formattable<DATA_T>) 
        {
            result += std::format("Data: {}", my_class.data());
        }
        // Should be replaced with correct std functionality
        else if constexpr (std::ostreambale<DATA_T>) 
        {
            std::ostringstream oss;
            oss << my_class.data();
            result += "Data: ";
            result += oss.str();
        }

        result += std::format("\nLocation: {}", my_class.location());

        return std::format_to(ctx.out(), "{}", result);
    }
};
Share Improve this question edited Mar 15 at 20:12 JeJo 33.5k7 gold badges55 silver badges95 bronze badges asked Mar 15 at 15:10 sakcakocasakcakoca 1194 bronze badges 2
  • formattable is connected to std::format, and has nothing to do with operator<<. – BoP Commented Mar 15 at 15:26
  • But you could test for "streamability" with something like requires { oss << my_class.data(); }. – BoP Commented Mar 15 at 15:27
Add a comment  | 

1 Answer 1

Reset to default 11

I tried to search it and could not find built-in checker to check if operator<< can be called on a type. I only found std::formattable<T> [...]

Yes, that is correct. For streamability via operator<<, there is no built-in trait in the standard library; therefore unfortunately, you must define your own check.

// Custom concept to check if a type is streamable via operator<<
template<typename T>
concept OStreamable = requires(std::ostream& os, const T& t) 
{
    { os << t } -> std::convertible_to<std::ostream&>;
};

With that update, you might do:

template<typename DATA_T>
struct std::formatter<MyClass<DATA_T>> : std::formatter<std::string> 
{
    auto format(const MyClass<DATA_T>& my_class, std::format_context& ctx) const
    {
        std::string result = std::format("Name: {}\n", my_class.name());

        // Check if DATA_T is formattable
        if constexpr (std::formattable<DATA_T, char>)
        {
            result += std::format("Data: {}", my_class.data());
        }
        // Use custom OStreamable concept for streamability
        else if constexpr (OStreamable<DATA_T>) {
            std::ostringstream oss;
            oss << my_class.data();
            result += "Data: " + oss.str();
        }

        result += std::format("\nLocation: {}", my_class.location());
        return std::format_to(ctx.out(), "{}", result);
    }
};

((See live demo))

发布评论

评论列表(0)

  1. 暂无评论