Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove perfect forwarding in std::make_format_args calls #326

Merged
merged 1 commit into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 6 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ namespace impl {
Helper(const char* s, std::size_t len): s(s, len) {}
template <typename... Args>
std::string operator()(Args&&... args) const {
return std::vformat(s, std::make_format_args(std::forward<Args>(args)...));
return std::vformat(s, std::make_format_args(args...));
}
};
} // namespace impl
Expand Down Expand Up @@ -376,7 +376,7 @@ int main() {

```cpp
constexpr auto operator""_f(const char* fmt, size_t) {
return[=]<typename... T>(T&&... Args) { return std::vformat(fmt, std::make_format_args(std::forward<T>(Args)...)); };
return[=]<typename... T>(T&&... Args) { return std::vformat(fmt, std::make_format_args(Args...)); };
}
```

Expand Down Expand Up @@ -431,7 +431,7 @@ namespace impl {
Helper(const char* s, std::size_t len): s(s, len) {}
template <typename... Args>
std::string operator()(Args&&... args) const {
return std::vformat(s, std::make_format_args(std::forward<Args>(args)...));
return std::vformat(s, std::make_format_args(args...));
}
};
} // namespace impl
Expand Down Expand Up @@ -513,7 +513,7 @@ struct std::formatter<Frac>:std::formatter<char>{
}
};
void print(std::string_view fmt,auto&&...args){
std::cout << std::vformat(fmt, std::make_format_args(std::forward<decltype(args)>(args)...));
std::cout << std::vformat(fmt, std::make_format_args(args...));
}
```

Expand All @@ -532,20 +532,11 @@ void print(std::string_view fmt,auto&&...args){

```cpp
void print(std::string_view fmt,auto&&...args){
std::cout << std::vformat(fmt, std::make_format_args(std::forward<decltype(args)>(args)...));
std::cout << std::vformat(fmt, std::make_format_args(args...));
}
```

此处我们没有显示声明模板形参,所以展开时不能使用以往的模板形参做完美转发的模板实参,但是根据形参包展开的规则。例
`args...`展开成`args1,args2,args3...`,而上式展开成

```cpp
std::forward<decltype(args1)>(args1),
std::forward<decltype(args2)>(arsg2),
std::forward<decltype(args3)>(args3),...
```

这样我们对每个应用到的参数用 decltype 取他的类型再作为完美转发的模板参数。这样调用 `vformat`,返回 string,可以使用 cout 直接输出。
这样调用 `vformat`,返回 string,可以使用 cout 直接输出。

而关于自定义 `std::formatter` 特化,我们需要知道的是:想要自定义 **std::formatter** 模板特化需要提供两个函数,**parse** 和 **format**。

Expand Down
4 changes: 2 additions & 2 deletions src/PDF版题目与答案/tex/questionAndAnswer02.tex
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ \subsection{答案}
framesep=2mm]{c++}
constexpr auto operator""_f(const char* fmt, size_t) {
return [=]<typename... T>(T&&... Args) {
return std::vformat(fmt, std::make_format_args(std::forward<T>(Args)...));
return std::vformat(fmt, std::make_format_args(Args...));
};
}
\end{minted}
Expand Down Expand Up @@ -80,7 +80,7 @@ \subsection{解析}
Helper(const char* s, std::size_t len): s(s, len) {}
template <typename... Args>
std::string operator()(Args&&... args) const {
return std::vformat(s, std::make_format_args(std::forward<Args>(args)...));
return std::vformat(s, std::make_format_args(args...));
}
};
} // namespace impl
Expand Down
22 changes: 3 additions & 19 deletions src/PDF版题目与答案/tex/questionAndAnswer03.tex
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ \subsection{标准答案}
}
};
void print(std::string_view fmt,auto&&...args){
std::cout << std::vformat(fmt, std::make_format_args(std::forward<decltype(args)>(args)...));
std::cout << std::vformat(fmt, std::make_format_args(args...));
}
\end{minted}

Expand All @@ -32,26 +32,10 @@ \subsection{解析}
framesep=2mm,
breaklines]{c++}
void print(std::string_view fmt,auto&&...args){
std::cout << std::vformat(fmt, std::make_format_args(std::forward<decltype(args)>(args)...));
std::cout << std::vformat(fmt, std::make_format_args(args...));
}
\end{minted}

由于使用了 C++20 简写函数模板,此处的完美转发就只能使用 decltype,显得有点诡异,其实很合理

展开的形式无非就是:

\begin{minted}[mathescape,
linenos,
numbersep=5pt,
gobble=2,
frame=lines,
framesep=2mm,
breaklines]{c++}
std::forward<decltype(args1)>(args1),
std::forward<decltype(args2)>(arsg2),
std::forward<decltype(args3)>(args3),...
\end{minted}

这两个格式化函数没必要再介绍,和第第二题的作用一样,很简单的调库。
这里实现策略使用了 C++20 简写函数模板。这两个格式化函数没必要再介绍,和第二题的作用一样,很简单的调库。

\clearpage
2 changes: 1 addition & 1 deletion src/群友提交/第02题/andyli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace impl {
Helper(const char* s, std::size_t len): s(s, len) {}
template <typename... Args>
std::string operator()(Args&&... args) const {
return std::vformat(s, std::make_format_args(std::forward<Args>(args)...));
return std::vformat(s, std::make_format_args(args...));
}
};
} // namespace impl
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第02题/happyd0g.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class formator {
public:
formator(const char* str):_inner_str(str) {}
auto operator () (auto&&... args) {
return std::vformat(_inner_str, std::make_format_args(std::forward<decltype(args)>(args)...));
return std::vformat(_inner_str, std::make_format_args(args...));
}
private:
const char* _inner_str;
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第02题/loser_linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ struct FormatterStream {

template<typename... Args>
std::string operator()(Args&&... args) {
return std::vformat(fmt_, std::make_format_args(std::forward<Args>(args)...));
return std::vformat(fmt_, std::make_format_args(args...));
}

std::string fmt_;
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第02题/mq卢瑟.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ constexpr auto operator""_f(const char* str, size_t)
{
return [=]<typename... T>(T&& ...args)
{
return std::vformat(str, std::make_format_args(std::forward<T>(args)...));
return std::vformat(str, std::make_format_args(args...));
};
}

Expand Down
4 changes: 1 addition & 3 deletions src/群友提交/第02题/子魂.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@

constexpr auto operator ""_f(const char* s, size_t l)
{
//return [s](auto&& ...vars){ return std::vformat(s, std::make_format_args(vars...)); };
//改用完美转发
return [s](auto&& ...vars){ return std::vformat(s, std::make_format_args(std::forward<decltype(vars)>(vars)...)); };
return [s](auto&& ...vars){ return std::vformat(s, std::make_format_args(vars...)); };
}

int main()
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第02题/心洗.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ auto operator ""_f(const char* text, size_t)
auto operator ""_f(const char* text, size_t)
{
return [text](auto&&... args) {
return std::vformat(text, std::make_format_args(std::forward<decltype(args)>(args)...));
return std::vformat(text, std::make_format_args(args...));
};
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第02题/涼風青葉.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct Formatter {

template<typename ...Args>
std::string operator()(Args &&...args) const {
return std::vformat(fmt, std::make_format_args(std::forward<Args>(args)...));
return std::vformat(fmt, std::make_format_args(args...));
}
};

Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第03题/CodeyZ.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ struct std::formatter<Frac, char> {

template<typename...Args>
auto print(std::string_view s,Args&&...args) {
std::cout << std::vformat(s,std::make_format_args(std::forward<Args>(args)...)) << '\n';
std::cout << std::vformat(s,std::make_format_args(args...)) << '\n';
}

int main() {
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第03题/SocialMean.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct std::formatter<Frac, charT> : std::formatter<int, charT> {
template <typename... Args>
void print(const char* fmt, Args&&... args) {
std::cout << std::vformat(fmt,
std::make_format_args(std::forward<Args>(args)...))
std::make_format_args(args...))
<< '\n';
}

Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第03题/happyd0g.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct std::formatter<Frac> : std::formatter<int> {
};

void print(const char* str, auto&& ... args) {
std::cout << std::vformat(str, std::make_format_args(std::forward<decltype(args)>(args)...));
std::cout << std::vformat(str, std::make_format_args(args...));
}

int main()
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第03题/jacky.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct std::formatter<Frac, CharT> : std::formatter<int, CharT> {

constexpr void print(const char* fmt, auto&&... args)
{
std::fputs(std::vformat(fmt, std::make_format_args(std::forward<decltype(args)>(args)...)).c_str(), stdout);
std::fputs(std::vformat(fmt, std::make_format_args(args...)).c_str(), stdout);
}

int main()
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第03题/joe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct std::formatter<Frac, CharT> : std::formatter<int, CharT>

void print(const char* fmt, auto&& ...frac)
{
std::cout<< std::vformat(fmt,std::make_format_args(std::forward<decltype(frac)>(frac)...));
std::cout<< std::vformat(fmt,std::make_format_args(frac...));
}

int main()
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第03题/loser_linker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ struct std::formatter<Frac, CharT> : std::formatter<int, CharT>

template<typename... Args>
void print(char const * str, Args&&... args){
std::cout << std::vformat(str,std::make_format_args(std::forward<Args>(args)...));
std::cout << std::vformat(str,std::make_format_args(args...));
}

int main()
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第03题/mq卢瑟.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ struct Frac {

template<typename... Args>
void print(std::string_view format_str, Args const&... args) {
std::cout << std::vformat(format_str, std::make_format_args(std::forward<decltype(args)>(args)...));
std::cout << std::vformat(format_str, std::make_format_args(args...));
}

template<>
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第03题/mq日.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ template<> struct std::formatter<Frac> : std::formatter<int>

void print(const char *str, auto &&...args)
{
std::cout << std::vformat(str, std::make_format_args(std::forward<decltype(args)>(args)...));
std::cout << std::vformat(str, std::make_format_args(args...));
}

int main()
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第03题/子魂.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

void print(const char* s, auto&&... vars)
{
std::cout << std::vformat(s, std::make_format_args(std::forward<decltype(vars)>(vars)...));
std::cout << std::vformat(s, std::make_format_args(vars...));
}

struct Frac
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第03题/心洗.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void print(auto&& text, auto&&... args)
{
std::cout << std::vformat(
std::forward<decltype(text)>(text),
std::make_format_args(std::forward<decltype(args)>(args)...));
std::make_format_args(args...));
}

int main()
Expand Down
2 changes: 1 addition & 1 deletion src/群友提交/第03题/涼風青葉.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct std::formatter<Frac> : std::formatter<char> {

template<typename T, typename ...Args>
void print(const T &fmt, Args &&...args) {
std::cout << std::vformat(fmt, std::make_format_args(std::forward<Args>(args)...));
std::cout << std::vformat(fmt, std::make_format_args(args...));
}

int main() {
Expand Down
Loading