
On 15 Aug 2014 at 12:42, Robert Ramey wrote:
You might try putting these propositions to the test by seeing what happens when one tries to explicitly specify type requirements to AFIO - assuming this has yet to be done. It would be interesting to know if this weren't possible.
Ah, this isn't needed in AFIO. And I suppose it is useful to explain why. AFIO is pure batch, so all APIs consume and emit std::vector<T> where T is an API-specific type. The mapping looks like this (subset): vector<async_io_op> <= dir(), rmdir(), file(), rmfile(), symlink(), rmsymlink() <= vector<async_path_op_req> vector<async_io_op> <= read(), write() <= vector<async_data_op_req<T>> pair< vector<future<pair<vector<directory_entry>, bool>>>, vector<async_io_op>
<= enumerate() <= vector<async_enumerate_op_req>
In other words, inputs are very strongly typed, and the input containers do considerable static and dynamic sanity checking. For example, read() and write() both accept vectors of async_data_op_req<T>, and async_data_op_req<T> will implicitly construct itself from any of: 1. boost::asio::const_buffer and mutable_buffer, or std::array or std::vector of const_buffer and mutable_buffer. 2. const T * and T * if also supplied with a size_t length and T is trivial. 3. const std::array<T, N> and non-const if T is trivial. 4. const std::basic_string<C, T, A> and non-const. 5. const std::vector<T, A> and non-const if T is trivial. 6. const void * and T * if also supplied with a size_t length in bytes. const semantics are adhered to, so passing a const input to read() raises a compile-time error. However write() will accept both const and mutable inputs. The reasons for the concreteness is because AFIO keeps a stable ABI which keeps platform-specific stuff in non-header code (it defaults to all header only though), and that means concrete types for the ABI stability. Because of that hard concrete type requirement, genericity at the next layer of API higher is tightly constrained, so I have made those constraints specific by a specifically defined input type constraint class per API which will handle the adaptation where it is possible, and won't compile otherwise. This produces very useful error messages because of the per-API input type checking - you can instantly see what is wrong and why because the compiler will print out all the constructor overloads which didn't match and why. I don't claim that this is a panacea - it does demand a lot of work from the programmer, and it is intentionally ungeneric and I have no idea how well it would scale. However, it concentrates all the brittleness into a single location and it generates very useful error messages. I'm certainly pleased with it to date. It should form an excellent basis for integration into the monadic continuations framework, which is what it was designed from the beginning to do. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/