implicit_cast has been removed, but this is sad

implicit_cast was once in cast.hpp, but as the comments says, it has been removed due to uncertain purpose. I have to purposes of which I am wondering how to do them otherwise: 1. take the address of the conversion 2. initialise a std::vector< int > with a boost::assign::list_of in a constructor initialiser The latter is a bit subtle. list_of uses a templated conversion operator to containers (but technically everything) and std::vector's ctor are then all tried with taking converted arguments, which leads into an ambiguity. Using implicit_cast solves the problem, since then the constructor call to std::vector and the call to the conversion operator in list_of are both taken as user defined conversions, and there can only be one of them. vector< int > v = list_of(1)(2); // works vector< int > v(list_of(1)(2)); // ambiguous ctor() : v(implicit_cast< vector< int > >(list_of(1)(2))) { } // ambiguous ctor() : v(list_of(1)(2)) { } // ambiguous Any thoughts on this? Regards, Jens

"Jens Theisen" <jens.theisen@transversal.com> wrote in message news:d1k5kt$k8m$1@sea.gmane.org... | implicit_cast was once in cast.hpp, but as the comments says, it has | been removed due to uncertain purpose. I have to purposes of which I am | wondering how to do them otherwise: | | 1. take the address of the conversion | 2. initialise a std::vector< int > with a boost::assign::list_of in a | constructor initialiser | | The latter is a bit subtle. indeed. | ambiguity. Using implicit_cast solves the problem, since then the | constructor call to std::vector and the call to the conversion operator | in list_of are both taken as user defined conversions, and there can | only be one of them. | | vector< int > v = list_of(1)(2); // works | | vector< int > v(list_of(1)(2)); // ambiguous | | ctor() : v(implicit_cast< vector< int > >(list_of(1)(2))) | { } // ambiguous | | ctor() : v(list_of(1)(2)) { } // ambiguous | | Any thoughts on this? what about ctor() : v( list_of(1)(2).to_container(v) ) { } ? -Thorsten

Thorsten Ottosen wrote:
ctor() : v( list_of(1)(2).to_container(v) ) { }
What are you proposing? You don't want to write to v before it's construction, do you? I see that this is somewhat anoying. Even with implicit_cast, because then you have to give the containers type in the initialisation again. I have read somewhere that template default arguments for functions might come into the language at some point in the future. In this case, one could write: template< typename Container, typename Unused = typename Container::iterator > operator Container() const { ... } This would then be a subsitution failure for all the single args a std::vector ctor takes untemplated (I may be mistaken), and thus giving no candidate for a ctor call. Unfortunately, this theory could only be tested on a compiler that already has this language extension. Does anyone know if there is one? Any other thoughts? Jens

"Jens Theisen" <jens.theisen@transversal.com> wrote in message news:d1nbk5$c0q$1@sea.gmane.org... | Thorsten Ottosen wrote: | > ctor() : v( list_of(1)(2).to_container(v) ) | > { } | | What are you proposing? You don't want to write to v before it's | construction, do you? | | I see that this is somewhat anoying. Even with implicit_cast, because | then you have to give the containers type in the initialisation again. to_container(v) is actually an existing work-around for compilers which can't even do Cont = list_of(...); All it does is to deduce the return type; it doesn't write to v, it finds its type. I should update the docs to make this a more used method of disambiguation -Thorsten

"Thorsten Ottosen" <nesotto@cs.auc.dk> writes:
"Jens Theisen" <jens.theisen@transversal.com> wrote in message news:d1nbk5$c0q$1@sea.gmane.org... | Thorsten Ottosen wrote: | > ctor() : v( list_of(1)(2).to_container(v) ) | > { } | | What are you proposing? You don't want to write to v before it's | construction, do you? | | I see that this is somewhat anoying. Even with implicit_cast, because | then you have to give the containers type in the initialisation again.
to_container(v) is actually an existing work-around for compilers which can't even do Cont = list_of(...);
All it does is to deduce the return type; it doesn't write to v, it finds its type.
I should update the docs to make this a more used method of disambiguation
In the spirit of recent work by Eric Niebler, I think you can use: v = 0?v: list_of(...) FWIW ;-) -- Dave Abrahams Boost Consulting www.boost-consulting.com

"David Abrahams" <dave@boost-consulting.com> wrote in message news:uwts0aeew.fsf@boost-consulting.com... | "Thorsten Ottosen" <nesotto@cs.auc.dk> writes: | > I should update the docs to make this a more used method of disambiguation | | In the spirit of recent work by Eric Niebler, I think you can use: | | v = 0?v: list_of(...) | | FWIW ;-) that is neat too, but still not optimal. How portable would SFINAE work with is_container<T>::value based on detecting member functions begin,end,size,empty ? -Thorsten

Thorsten Ottosen wrote:
| v = 0?v: list_of(...) | | FWIW ;-)
that is neat too, but still not optimal. How portable would SFINAE work with is_container<T>::value based on detecting member functions begin,end,size,empty ?
How do you want to apply SNIFAE in a conversion operator? Jens

"Jens Theisen" <jens.theisen@transversal.com> wrote in message news:d1okmn$bjv$1@sea.gmane.org... | Thorsten Ottosen wrote: | > | v = 0?v: list_of(...) | > | | > | FWIW ;-) | > | > that is neat too, but still not optimal. How portable would | > SFINAE work with is_container<T>::value based on | > detecting member functions begin,end,size,empty ? | | How do you want to apply SNIFAE in a conversion operator? Hm.. yeah, I thought something like #include <boost/utility/enable_if.hpp> #include <boost/type_traits/is_same.hpp> using namespace boost; struct Foo { template< class T > operator typename enable_if< is_same<T,int>, int>::type() { return 0; } }; int main() { Foo f; int i = f; } would work.

Thorsten Ottosen wrote:
Hm.. yeah, I thought something like
operator typename enable_if< is_same<T,int>, int>::type() {
would work.
I doubt that, because it should be impossible to deduce the type. If anyone know of a trick to do a SNIFAE in a conversion operators, or knows that it is not possible, we would like to hear. Jens

Jens Theisen <jens.theisen@transversal.com> writes:
Thorsten Ottosen wrote:
Hm.. yeah, I thought something like
operator typename enable_if< is_same<T,int>, int>::type() { would work.
I doubt that, because it should be impossible to deduce the type.
If anyone know of a trick to do a SNIFAE in a conversion operators, or knows that it is not possible, we would like to hear.
I think the enable_if docs make it quite clear that it can't be done. -- Dave Abrahams Boost Consulting www.boost-consulting.com

"Jens Theisen" <jens.theisen@transversal.com> wrote in message news:d1p6ou$4b4$1@sea.gmane.org... | Thorsten Ottosen wrote: | > Hm.. yeah, I thought something like | | > operator typename enable_if< is_same<T,int>, int>::type() | > { | > | > would work. | | I doubt that, because it should be impossible to deduce the type. | | If anyone know of a trick to do a SNIFAE in a conversion operators, or | knows that it is not possible, we would like to hear. it seems that several people would like <boost/std_forward.hpp>; I think Eric Niebler has already made one for his range_ex stuff. Given this, wouldn't we be able to make all the relevant conversion funcitions like template< class T, A > operator std:vector<T,A>() const; ? -Thorsten

Jens Theisen <jens.theisen@transversal.com> writes:
implicit_cast was once in cast.hpp, but as the comments says, it has been removed due to uncertain purpose.
It was restored to boost/implicit_cast.hpp once we understood what it was supposed to do. -- Dave Abrahams Boost Consulting www.boost-consulting.com
participants (4)
-
David Abrahams
-
Gennadiy Rozental
-
Jens Theisen
-
Thorsten Ottosen