带有用户定义类的c++折叠表达式



我想制作一个带有多个参数的日志函数,我也想用我的类调用日志函数
这是我的代码(编译器:Visual studio 2019或x86-64 gcc9.2(

问题1>我无法理解日志函数。有可能像这样使用fold表达式吗?(此函数来自spdlog库(

问题2>如何在Mystruct类中使用log函数
log(1, MyStruct(1, 1.1f, "hello world"s)); // compiler error

#include <cstdio>
#include <iostream>
#include <string>
#include <sstream>
template<typename ... Args>
void log(int level, Args const& ... args)
{
std::ostringstream stream;
using List = int[];
(void)List {
0, ((void)(stream << args), 0) ...
};
std::cout << stream.str() << std::endl;
}
class MyStruct
{
public:
int val1 = 0;
float val2 = 0.f;
std::string val3;
MyStruct(int v1, float v2, std::string_view const& v3) : val1(v1), val2(v2), val3(v3) {};
std::string to_string() const
{
std::stringstream stream;
stream << "val1=" << val1 << ", val2=" << val2 << ",val3=" << val3;
return stream.str();
}
};
std::ostringstream& operator<< (std::ostringstream& stream, MyStruct&& val)
{
auto str = val.to_string();
std::operator <<(stream, str);
return stream;
}
void work_good()
{
using namespace std::string_literals;  
log(1, 1.1f, "hello world"s);
}
void compile_error()
{
using namespace std::string_literals;  
log(1, MyStruct(1, 1.1f, "hello world"s));
}
int main()
{
work_good();
}

问题1>我无法理解日志函数。是否可以使用像这样折叠表情?

准确地说,它没有使用fold表达式(因为C++17(。请参阅C++11支持的包扩展,是的,它是log中的有效用法。

后面跟着省略号的模式,其中至少一个参数包的名称至少出现一次,被扩展为该模式的零个或多个逗号分隔的实例,其中参数包的名字被包中的每个元素按顺序替换。

问题2>如何将日志函数与Mystruct类一起使用?

您声明了operator<<,将MyStruct作为右值引用,但在log中,参数被传递给operator<<作为左值,不能绑定到右值引用。您可以将operator<<更改为将左值引用为const,这适用于左值和右值。例如

std::ostringstream& operator<< (std::ostringstream& stream, const MyStruct& val)
{
auto str = val.to_string();
std::operator <<(stream, str);
return stream;
}

实时

我更改了一些代码引用的答案。我想日志功能更通用

namespace nlog
{
class MyStruct
{
public:
int val1 = 0;
float val2 = 0.f;
std::string val3;
MyStruct(int v1, float v2, std::string_view const& v3) : val1(v1), val2(v2), val3(v3) {};
std::string to_string() const
{
std::stringstream stream;
stream << "val1=" << val1 << ", val2=" << val2 << ",val3=" << val3;
return stream.str();
}
};
template < typename T, typename decltype(std::declval<T>().to_string())* = nullptr>
std::ostream& operator<< (std::ostream& stream, T&& val)
{
auto str = val.to_string();
std::operator <<(stream, str);
return stream;
}

template <typename ... Ts>
void tolog(Ts && ...args)
{
std::stringstream strbuf;
(strbuf << ... << std::forward<Ts>(args));
std::cout << strbuf.str() << std::endl;
}
template <typename ... Ts>
void toout(Ts && ...args)
{
(std::cout << ... << args);
}
};
namespace nlog
{
void Test1()
{
using namespace std::string_literals;
std::stringstream strbuf;
strbuf << MyStruct(0, 0.1f, "Eric"s);
std::cout << strbuf.str() << std::endl;
}
void Test2()
{
using namespace std::string_literals;
tolog(1, 1.1f, "hello world"s);
}
void Test3()
{
using namespace std::string_literals;
tolog("I like this func val=", 100, ", youvalue=", 1.0f, ", MyStruct=",  MyStruct(0, 0.1f, "Eric"s));
}
};
int main()
{
nlog::Test1();
nlog::Test2();
nlog::Test3();
}

最新更新