如何检测类型是否可以流传输到std :: ostream? [英] How can I detect if a type can be streamed to an std::ostream?

查看:171
本文介绍了如何检测类型是否可以流传输到std :: ostream?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写一个类型trait来检测类型是否具有适合用于输出流的重载操作符<<()。

I'm trying to write a type trait to detect if a type has overloaded operator<<() suitable to use to an output stream.

m缺少一些东西,因为我总是得到一个简单的空类没有任何运算符。

I'm missing something because I'm always getting true for a simple empty class with no operators at all.

这里的代码:

template<typename S, typename T>
class is_streamable
{
    template<typename SS, typename TT>
    static auto test(SS&& s, TT&& t)
    -> decltype(std::forward<SS>(s) << std::forward<TT>(t));

    struct dummy_t {};
    static dummy_t test(...);

    using return_type = decltype(test(std::declval<S>(), std::declval<T>()));

public:
    static const bool value = !std::is_same<return_type, dummy_t>::value;
};

class C {};

int main() {
    std::cout << is_streamable<std::stringstream, C>::value << std::endl;
    return 0;
}

输出:

1

这里是在ideone:https://ideone.com/ikSBoT

Here it is in ideone: https://ideone.com/ikSBoT

我做错了什么?

推荐答案

显然这个重载的运算符<< traling中的表达式返回类型valid:

It's apparently this overload of operator<< that's stepping in your way and making the expression in traling return type valid:

template< class CharT, class Traits, class T >
basic_ostream< CharT, Traits >& operator<<( basic_ostream<CharT,Traits>&& os,
                                            const T& value );

请参阅此参考页。它是一个简单的转发器(调用 os< ),它是在C ++ 11中添加的,允许插入到rvalue-streams,因为它们不绑定重载

See (3) on this reference page. It's a simple forwarder (calling os << value) that was added in C++11 to allow insertion to rvalue-streams because they don't bind to overloads taking an lvalue reference.

所以,问题是 std :: declval< SS>()返回一个右值引用和这个重载踢。调用本身是良好的形式,但因为函数本身没有被实例化,你不会得到一个错误,即使值不可流化。

So, the problem is that std::declval<SS>() returns an rvalue reference and this overload kicks in. The call itself is well-formed, but because the function itself does not get instantiated you don't get an error even if value is not streamable.

如果您明确要求引用值为$ lt code> std :: declval< SS&>()

This can be sidestepped if you explicitly ask for lvalue reference: std::declval<SS&>().

我也建议一个稍微不同的实现,而不传递流和值到 test 。您可以在 decltype 中直接使用 declval 。与逗号运算符一起,它看起来像这样:

I'd also suggest a slightly different implementation, without passing stream and value to test. You can use declval directly inside decltype. Together with comma operator, it looks like this:

#include <type_traits>
#include <utility>
#include <iostream>
#include <sstream>

template<typename S, typename T>
class is_streamable
{
    template<typename SS, typename TT>
    static auto test(int)
    -> decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() );

    template<typename, typename>
    static auto test(...) -> std::false_type;

public:
    static const bool value = decltype(test<S,T>(0))::value;
};

class C {};

int main() {
    std::cout << is_streamable<std::stringstream, C>::value << std::endl;
    return 0;
}

这篇关于如何检测类型是否可以流传输到std :: ostream?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆