gpt4 book ai didi

c++ - 如何使用 is_invocable() 来创建用于重载 << 以打印对象的模板?

转载 作者:行者123 更新时间:2023-11-28 04:21:41 24 4
gpt4 key购买 nike

我很欣赏这个 stackoverflow 问题的答案 Generic implementation of operator<< function in terms of the dump member function

然而,answer by Richard Hodges建议可以使用 C++17 的 is_invocable() 来简化此解决方案。

当我尝试使用 is_invocable() 实现解决方案时,出现编译错误。

我在没有 is_invocable 的代码周围有一个#ifdef 0称呼。行得通。

我需要如何更改我的代码才能使 is_invocable 调用起作用?

谢谢!

编译错误:

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 是有帮助的.

关于c++ - 如何使用 is_invocable() 来创建用于重载 << 以打印对象的模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55314253/

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