我真的很希望能够有一个自由函数,以适应其给出的任何类型。
例如
template <typename T> bool ReadLine(T & reader, std::string & line)
{
return reader.ReadString(line);
}
对于某些T,正确的函数是reader.ReadString(buffer)。但是对于其他人,应该是reader.ReadLine(buffer)。当然,将来可能还会有其他模式。关键是使自由函数ReadLine(from,into)适应任何合理的from&into集(我已将目标缓冲区设置为std::string,以简化此处的操作)。
现在,我可以为我想要的任何具体类型制作ReadLine的非模板版本,但我真正需要的是能够部分专用于类型的类,例如那些支持模式reader.ReadString()的对象使用该样式,以及那些支持reader.ReadLine()的样式,并且将来我可以添加其他样式而不会干扰任何已经起作用的样式。
我知道我可以创建一个策略类,例如LineReaderPolicy,它为给定的T知道要使用哪种模式(它必须根据T进行部分专门化才能将其映射到正确的模式。
但是,有没有更好,更多的C++ 14解决方案呢?
这就是“上帝,模板似乎真的非常非常有用……但是对于这个不断出现的问题……”
使用C++ 11/14,可堆肥性比以往任何时候都更好,但是看来这个根本问题还没有解决吗?还是??
您如何建议我编写一组自由函数以适应任何合理的T来从中读取一行? T是否为字符串流,输出迭代器,文件句柄,字符串,字符串 View 等,等等。
我只是不能认为C++真的已经成熟,直到我可以编写出合理的
template <typename T> size_t length(T t) { return t.size(); }
为此,我可以将其扩展为任何合理的T,而不再需要编写了解T的这么多细节的代码,而是可以通过这种灵活的自由功能适配器与大量T互操作...
最佳答案
如果您可以确保定义了reader.ReadString
或reader.ReadLine
中的至少一项,请使用SFINAE来控制重载(Live at Coliru):
template <typename T>
auto ReadLine(T& reader, std::string& line) -> decltype(reader.ReadString(line)) {
return reader.ReadString(line);
}
template <typename T>
auto ReadLine(T& reader, std::string& line) -> decltype(reader.ReadLine(line)) {
return reader.ReadLine(line);
}
不适用的实现将触发SFINAE,并从重载集中删除,仅保留正确的实现。
在C++ 14中,您可以省略尾随的返回类型,而只需使用返回类型推导。
在将来的C++版本中,Concepts Lite将使此操作更干净。给定区分两种不同读者的概念-
StringReader
和LineReader
:template <typename T>
concept bool StringReader() {
return requires(T& reader, std::string& line) {
{reader.ReadString(line)} -> bool;
};
}
template <typename T>
concept bool LineReader() {
return requires(T& reader, std::string& line) {
{reader.ReadLine(line)} -> bool;
};
}
您将能够直接将实现限制为对这些概念建模的一组类型:
bool ReadLine(StringReader& reader, std::string& line) {
return reader.ReadString(line);
}
bool ReadLine(LineReader& reader, std::string& line) {
return reader.ReadLine(line);
}
希望您能够在其他地方重用这些概念,以证明“新的更好的”语法比旧的讨厌的语法长得多。 Concepts Lite还可以通过显式消除歧义来处理为两个概念建模的类型:
template <typename T>
requires StringReader<T>() && LineReader<T>()
bool ReadLine(T& reader, std::string& line) {
// Call one, or the other, or do something completely different.
}
关于c++ - 自由函数包装的SFINAE技术,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22409356/