如何约束模板类型T可作为std::wfstream::operator<<的参数
解决std::wfstream::operator<<的模板类型约束问题
要限定模板类型T能被std::wfstream的operator<<接受,你需要直接在requires子句中模拟流操作的合法性,而不是用std::invoke——因为std::wfstream的operator<<既有成员函数版本,也有大量非成员函数重载(比如针对字符串、字面量的),std::invoke无法统一覆盖这些情况。
正确的约束写法
写法一:直接使用requires表达式
修正你代码中的笔误(函数内的k应为t),并添加requires约束:
#include <fstream> #include <string> template <typename T> requires requires (std::wfstream fs, T t) { fs << t; } void foo(T t) { std::wfstream file{}; file << t; } int main() { // 标准C++中main的返回类型必须是int std::string str; std::wstring wstr; foo(str); // 编译错误:符合预期,std::wfstream无对应operator<< foo(wstr); // 正常通过 foo("s"); // 正常通过(调用basic_ostream::operator<<(const void*)) foo(L"s"); // 正常通过 }
写法二:定义可复用的Concept
如果需要在多个模板中复用这个约束,可以定义一个Concept:
#include <fstream> #include <string> template <typename T> concept WritableToWFStream = requires (std::wfstream fs, T t) { fs << t; }; template <WritableToWFStream T> void foo(T t) { std::wfstream file{}; file << t; } int main() { std::string str; std::wstring wstr; foo(str); // 编译错误 foo(wstr); // 通过 foo("s"); // 通过 foo(L"s"); // 通过 }
原理说明
requires (std::wfstream fs, T t) { fs << t; }是一个requires表达式,它会让编译器检查:当存在一个std::wfstream对象fs和T类型的对象t时,表达式fs << t是否合法。这种写法能自动适配所有operator<<的重载形式,不管是成员函数还是非成员函数,完美匹配你的需求。
内容的提问来源于stack exchange,提问作者VITERNATOFUCRUP
相关产品推荐
相关产品推荐

