如何使用 is_invocable() 创建用于重载<<打印对象的模板?
How can I use is_invocable() to create a template for overloading << for printing out an object?
我感谢此堆叠式问题的答案,该问题是操作员的通用实现&lt;&lt;根据转储成员功能的功能
但是,理查德·霍奇斯(Richard Hodges)的答案表明,C 17的IS_invocable()可用于简化此解决方案。
当我尝试使用is_invocable()实现解决方案时,我会收到一个编译错误。
我在无需is_invocable
调用的情况下有效的代码周围有一个#ifdef 0。有效。
我需要如何更改代码以获取IS_INVOCABLE CALL的工作?
谢谢!
编译错误:
main.cpp:16:46: error: reference to non-static member function must be called
static_assert(std::is_invocable<decltype(t.dump),
~~^~~~
main.cpp:47:13: note: in instantiation of function template specialization 'operator<<<Foobar, char>' requested here
std::cout << foobar << std::endl;
^
main.cpp:32:32: note: possible target for call
std::basic_ostream<charT> &dump(std::basic_ostream<charT> &o) const
代码:
#include <iostream>
#include <string>
#include <type_traits>
template<typename T, typename charT>
auto operator<<(std::basic_ostream<charT> &str, const T &t) -> decltype(t
.dump(str))
{
#if 0
static_assert(std::is_same
<decltype(t.dump(str)),
std::basic_ostream<charT> &>::value,
".dump(ostream&) does not return ostream& !");
#else
static_assert(std::is_invocable<decltype(t.dump),
std::basic_ostream<charT> &>::value,
".dump(ostream&) does not return ostream& !");
#endif
return t.dump(str);
}
class Foobar {
public:
Foobar(std::string nameArg)
:
name(nameArg)
{}
template<typename charT>
std::basic_ostream<charT> &dump(std::basic_ostream<charT> &o) const
{
return (o << name);
}
private:
std::string name;
};
int main()
{
Foobar foobar("private name");
std::cout << foobar << std::endl;
return 0;
}
根据@oktalist的答案,我对我的代码进行了如下修改。我留下原始代码,因此问题很有意义。修改的代码未编译。我相信我只是错过了如何工作的细微差别。
编译错误是
error: invalid operands to binary expression ('std::__1::ostream' (aka 'basic_ostream<char>') and 'Foobar')
std::cout << foobar << std::endl;
这是未编译的更新代码:
#include <iostream>
#include <string>
#include <type_traits>
template<typename T, typename charT>
auto operator<<(std::basic_ostream<charT> &str, const T &t) ->
decltype(t.dump)
{
static_assert(std::is_invocable_r<
std::basic_ostream<charT> &, // return type
decltype(&T::dump), // invocable type
T const &, // first arg type (implicit this)
std::basic_ostream<charT> & // second arg type
>::value, "dump(ostream&) does not return ostream& !");
return t.dump(str);
}
class Foobar {
public:
Foobar(std::string nameArg)
:
name(nameArg)
{}
template<typename charT>
std::basic_ostream<charT> &dump(std::basic_ostream<charT> &o) const
{
return (o << name);
}
private:
std::string name;
};
int main()
{
Foobar foobar("private name");
std::cout << foobar << std::endl;
return 0;
}
首先, decltype(t.dump)
是无效的。您想要decltype(&T::dump)
。
其次,如果要检查返回类型,则需要std::is_invocable_r
,并且也需要提供两种参数类型:
static_assert(std::is_invocable_r<
std::basic_ostream<charT> &, // return type
decltype(&T::dump), // invocable type
T const &, // first arg type (implicit this)
std::basic_ostream<charT> & // second arg type
>::value, ".dump(ostream&) does not return ostream& !");
在您的情况下,以上是不起作用的,因为 dump
是函数模板。
std::is_invocable_r<
std::basic_ostream<charT> &,
decltype(&T::template dump<charT>),
T const &,
std::basic_ostream<charT> &
>::value
那会起作用,但是您将自己限制在dump
的某个签名中,我不知道为什么您认为在这里使用is_invocable
是有帮助的。
相关文章:
- 如何循环打印顶点结构
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 如何在c++中打印目录
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 有一个打印语句的函数是一种糟糕的编程实践吗
- 在线编译器中的分段C++没有打印消息
- 呼叫运营商<<临时
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 如何将结构插入到集合中并打印集合的成员
- 在循环C++中指定字符串之后,不会打印该字符串
- 以螺旋方式打印矩阵的程序.(工作不好)
- 从控制台中删除最后打印的元素
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- 如何仅使用对象名称打印特定于对象的成员
- 过载输出<<用于类的运算符,以打印其中的元组
- 重载operator< & lt;作为会员打印
- 重载& lt; & lt;用于打印自定义异常的操作符
- 如何显示/打印字符串对象?cout & lt; & lt;Int工作,count <<字符串
- 什么会导致死亡<<变量& lt; & lt;“ t";当输出超过终端宽度时,打印空白而不是值