gpt4 book ai didi

c++ - 覆盖所有类型的 operator<<

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:07:50 28 4
gpt4 key购买 nike

我对尝试编写 std::cout << x 时出现的编译错误感到有点恼火, 和左移运算符它没有为 x 定义.无法将 x 转换为这个,无法将 x 转换为那个...几屏无用的错误消息。

我想专攻operator<<(std::ostream&, const T&)对于尚未定义此类运算符的所有类型。我可以在里面放一个静态断言,并使编译错误消息比现在更清晰。

我的第一次尝试如下。

template<typename T, typename = void>
struct Has : public std::false_type {};

template<typename T>
struct Has<T, decltype(void(
std::declval<std::ostream&>() << std::declval<T>()
))> : public std::true_type {};

template<typename T>
auto operator<<(std::ostream& out, const T&)
-> typename std::enable_if<
!Has<T>::value,
std::ostream&>::type
{
return out << "my operator";
}

编译失败,因为超过了最大模板深度。的确,我的operator<<调用 Has按顺序调用的特化 operator<< ,再次检查我的过载,依此类推。

最简单的版本也不起作用:std::ostream& << const char* 的模糊重载| .嗯,意料之中。

template<typename T>
std::ostream& operator<<(std::ostream& out, const T&)
{
return out << "my operator";
}

我怎样才能完成任务?或者,一般来说,除了那些已经可以传递给函数的参数类型之外,我如何为所有参数类型定义函数?

最佳答案

一般来说你不能。但这是 ,所以如果你愿意作恶,你也可以。

namespace named_operator {
template<class D>struct make_operator{constexpr make_operator(){}};

template<class T, char, class O> struct half_apply { T&& lhs; O const& o; };

template<class Lhs, class Op>
half_apply<Lhs, '<', Op> operator<( Lhs&& lhs, make_operator<Op>const & o ) {
return {std::forward<Lhs>(lhs), o};
}

template<class Lhs, class Op, class Rhs>
auto operator<( half_apply<Lhs, '<', Op>&& lhs, Rhs&& rhs )
-> decltype( named_invoke( std::forward<Lhs>(lhs.lhs), lhs.o, std::forward<Rhs>(rhs) ) )
{
return named_invoke( std::forward<Lhs>(lhs.lhs), lhs.o, std::forward<Rhs>(rhs) );
}
}
namespace utility {
namespace details {
template<class...>struct voider{using type=void;};
}
template<class...Ts>using void_t=typename details::voider<Ts...>::type;
namespace details {

template<template<class...>class, class, class...>
struct can_apply:std::false_type{};
template<template<class...>class Z, class...Ts>
struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z,void,Ts...>;
}
namespace streaming {
namespace details {
template<class T>
using ostream_r = decltype( std::cout << std::declval<T&&>() );
}
template<class T>
using can_ostream = utility::can_apply<details::ostream_r, T>;

struct out_tag: named_operator::make_operator<out_tag> {};
static const out_tag out;
template<class T>
std::ostream& named_invoke( std::ostream& os, out_tag, T const& t ) {
static_assert( can_ostream<T const&>{}, "This type cannot be streamed" );
return os<<t;
}
template<class T,
std::enable_if_t< can_ostream<T const&>{}, int> =0 // breaks MSVC
>
std::ostream& named_invoke( std::ostream& os, out_tag, T const& t ) {
return os<<t;
}
}

如果我写对了,

struct no_worky {};
no_worky bob;
using streaming::out;
std::cout <out< bob;

同时编译失败并生成友好消息

std::cout <out< 7;

电话 std::cout << 7 .

我认为这不值得。

关于c++ - 覆盖所有类型的 operator<<,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46894267/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com