Le 26/11/14 12:00, Vladimir Batov a écrit : I have started a new thread to try to clarify what I have in my mind.
... I'm looking on how all these conversions can be made safer. ... OK, Vicente, my most humble apologies for snipping all the stuff you typed that flew right over my head and made me feel stupid. I have to be brutally honest I did not understand your "idea to state explicitly that you want a explicit conversion but don't state to what" and your "implicit explicit conversion thing". You obviously put a lot of thought into it but I personally did not get *what problem* exactly you are trying to solve. I personally do not feel there is a conversion-related problem that needs fixing... On the other hand I do not know Haskell, so it may well be that I do not know what I am missing. :-) I just hope that other people you'll present your idea to will be smarter than me to appreciate it. Do you have any links to slow-pace tutorial/explanation/justification of what you are trying to propose that I could peruse without hurry?
I will try again, but I'm not sure I will be clearer this time :( NOTE: this has nothing to be with a library solution, not with the current C++ language, and so it could be out of the scope of this ML. Please, skip this post if you are not concerned by how other language can influence C++. Just 3 references to Haskell * http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictur... * http://en.wikibooks.org/wiki/Haskell/Understanding_monads * https://www.haskell.org/haskellwiki/Polymorphism C++ doesn't takes in account the result type of a function during overload resolution. This has its advantages and liabilities. Consider the following situation. Given void f(W<T>); template B<A> make(A v) { return B<A>(v); } It seems reasonable to define a function void g(X x) { f(make<W>(x)); } Here we are conveying the context via the template class W, that is, we are explicit about the context. Consider now a system on which the overload resolution takes in account the target type. Let me use [] instead of () to wrap the function parameters and arguments for this kind of functions so that we can identify them in an easy way. First of all we need to identify the context on which the function has a sens. Let me call this construction just *context*. template * context* Builder { template <class T> B<T> make [ T v ]; }; The function 'make' has only one argument, but its result type depends on the context. void g(X x) { f( make[x] ); } The result of make[x] has no sens if we don't know what the target type is. In the expression f( make [x] ) the target of the expression make [x] is W<X> and the context would be W. So the overload that will be taken would be Builder<W>::make[X]. We need to say what Builder<W>::make[X] means, if it would even has a meaning. In order to give a meaning to this expression we need to map W as a builder * template <> context* Builder<W> { template <class T> W<T> make [ T v ] { return whatever_you_want_that_returns_w_t(c); } }; Note that in Haskell the keywords are class for context, and instance for context_map. In some way, we could say that Builder is a type-class having types as instances, and a type belong to this type-class if there is an explicit mapping. This has a lot to be with the abandoned Concept-0x proposal, which was based on signature mapping. The current C++ Concept Lite trend is to have a default mapping for those types that satisfy a set of some syntactical constraint. I think that we could build something similar to Concept-0x on top of Concept Lite, but of course without the help of the language it would be more verbose as we will need to add an indirection. There are also some similarities with the object oriented approach, but instead of having an explicit object you have an deduced context that determines the function to call using static polymorphism. This kind of polymorphism is called ad-hoc polymorphism in the literature an in particular it is used in Haskell and Rust. Another example, this time with a variable * context* ProbablyValued PV { // constructors PV make [ ValueType<PV> v ]; constexpr PV none; // accessors ... }; Ad-hoc polymorphism has its own liabilities also of course. Best, Vicente P.S. I'm not serious. Having another way to do polymorphic calls in c++ is not reasonable, or is it?