I have the following - simplified -- C++11 code used to abstract away reading from an object store or from the file system:
ObjectLikeReader::openis a virtual function returning aHandleimplementation.Handle::readreads something from the underlying object.
class Handle {
public:
virtual std::string read() = 0;
virtual ~Handle() = default;
};
class ObjectLikeReader {
public:
virtual std::unique_ptr<Handle> open() = 0;
virtual ~ObjectLikeReader() = default;
};
// Specialization
class FileReader : public ObjectLikeReader {
public:
std::unique_ptr<Handle> open() override;
private:
class InternalHandle;
};
class FileReader::InternalHandle : public Handle {
public:
InternalHandle(){};
std::string read() override {
return "hello";
}
};
std::unique_ptr<Handle> FileReader::open() {
return std::unique_ptr<Handle>(new InternalHandle());
}
std::string read(ObjectLikeReader* reader) {
return reader->open()->read();
}
int main() {
FileReader r;
std::cout << read(&r) << std::endl;
}
All the dispatch is done using virtual functions, and working perfectly fine. Apart from performance in tight loop, which commands having a look at static polymorphism:
#include <iostream>
#include <string>
template <class T>
class Handle {
public:
std::string read() {
return static_cast<T*>(this)->read();
}
protected:
~Handle() = default;
};
template <class T, class H>
class ObjectLikeReader {
public:
Handle<H> open() {
return static_cast<T*>(this)->open();
}
protected:
~ObjectLikeReader() = default;
};
// Specialization
class FileReaderHandle : Handle<FileReaderHandle> {
public:
FileReaderHandle(){};
std::string read() {
return "hello";
}
};
class FileReader : public ObjectLikeReader<FileReader, FileReaderHandle> {
public:
FileReaderHandle open() {
return FileReaderHandle();
}
};
int main() {
FileReader r;
std::cout << r.open().read() << std::endl;
}
I am not quite satisfied of this implementation. Is there a way to achieve the same functionality as the second example?:
- Without requiring the double template parameter (traits maybe? not sure...),
- Ideally without having to make the handle class public.
Thanks!
Edit: Fixed stupid missing constructor definition causing compilation error.
Aucun commentaire:
Enregistrer un commentaire