Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

a type_trait to tell if a particular constructor exists?

286 views
Skip to first unread message

John Salmon

unread,
Jun 15, 2009, 2:45:31 AM6/15/09
to

Is there a type_trait that tells me whether a particular constructor
exists. For example, I'd like to know whether TO has a
constructor from a specific type, FROM. This is almost the
same as is_convertible in boost and tr1, but is_convertible
returns false if the constructor is explicit, and that's not
what I want.

I.e., this prints 0 for me.

#include <boost/type_traits.hpp>
#include <iostream>

struct From;

struct To{
explicit To(const From&);
};

int main(int argc, char **argv){
std::cout << boost::is_convertible<From, To>::value << "\n";
return 0;
}

So, is there a way to determine if a particular constructor exists
regardless of whether it's explicit?

Why do I want this? I'd like to convert FROM to TO with a bona fide
constructor, but fall back to something like lexical_cast if not.
For this purpose, an explicit constructor is fine. I.e., I
want to write something like:

template <typename FROM, typename TO, bool use_ctor>
TO convert_impl(const FROM& f);

// specialize the no-constructor case
template <typename FROM, typename TO>
TO convert_impl<FROM, TO, false> convert_impl(const FROM& f){
return lexical_cast<TO>(f);
}

// specialize the has-constructor case
template <typename FROM, typename TO>
TO convert_impl<FROM, TO, true> convert_impl(const FROM& f){
return TO(f);
}

template <typename FROM, typename TO>
TO convert(const FROM& f){
return convert_impl<FROM, has_constructor<FROM, TO>::value>(f);
}

Thanks,
John Salmon

--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

litb

unread,
Jun 15, 2009, 1:53:19 PM6/15/09
to
On 15 Jun., 08:45, John Salmon <jsal...@thesalmons.org> wrote:
> Is there a type_trait that tells me whether a particular constructor
> exists. For example, I'd like to know whether TO has a
> constructor from a specific type, FROM. This is almost the
> same as is_convertible in boost and tr1, but is_convertible
> returns false if the constructor is explicit, and that's not
> what I want.
>> [...]

This one works for me with g++ 4.4 and comeau online compiler, and
looks like valid C++03.

#include <vector>
#include <string>

namespace detail {
template<int> struct D { };
typedef char yes[1];
typedef char no[2];

template<typename T, typename U>
yes &f(int, D<sizeof T(*(U*)0)>* = 0);

template<typename T, typename U>
no &f(...);
}

template<typename To, typename From>
struct IsExplicitlyConvertible {
static bool const value = (sizeof detail::f<To, From>(0) ==
sizeof(detail::yes));
};

int main() {
IsExplicitlyConvertible<std::vector<int>, int>::value; // true
IsExplicitlyConvertible<float, int>::value; // true
IsExplicitlyConvertible<std::string, int>::value; // false
}

For some weird reason, it fails to parse the f functions if they are
static member templates ("invalid use of type parameter 'T'").
Sometimes, it rises errors about not implemented expression manglings
(for the template signature). In this form, it seems to work for both
gcc and comeau.

Mathias Gaunard

unread,
Jun 15, 2009, 1:54:33 PM6/15/09
to
On 15 juin, 08:45, John Salmon <jsal...@thesalmons.org> wrote:
> Is there a type_trait that tells me whether a particular constructor
> exists.

You can implement that either using C++0x concepts or SFINAE for
expressions.

Roman Perepelitsa

unread,
Jun 15, 2009, 7:38:45 PM6/15/09
to
On 15 June, 19:54, Mathias Gaunard <loufo...@gmail.com> wrote:
> > Is there a type_trait that tells me whether a particular constructor
> > exists.
>
> You can implement that either using C++0x concepts or SFINAE for
> expressions.

I'm pretty sure it's impossible to implement in C++03 for
constructors with more than one parameter.

See the same discussion in boost-users mailing list:
http://groups.google.com/group/boost-list/browse_thread/thread/e15440218b85122a

Roman Perepelitsa.

CornedBee

unread,
Jun 15, 2009, 7:37:51 PM6/15/09
to
On Jun 15, 7:54 pm, Mathias Gaunard <loufo...@gmail.com> wrote:
> On 15 juin, 08:45, John Salmon <jsal...@thesalmons.org> wrote:
>
> > Is there a type_trait that tells me whether a particular constructor
> > exists.
>
> You can implement that either using C++0x concepts or SFINAE for
> expressions.

Either way you need C++0x. But at least extended SFINAE is already
implemented in usable compilers.

Sebastian

litb

unread,
Jun 16, 2009, 2:17:09 AM6/16/09
to
On 16 Jun., 01:37, CornedBee <wasti.r...@gmx.net> wrote:
> On Jun 15, 7:54 pm, Mathias Gaunard <loufo...@gmail.com> wrote:
>
> > On 15 juin, 08:45, John Salmon <jsal...@thesalmons.org> wrote:
>
> > > Is there a type_trait that tells me whether a particular constructor
> > > exists.
>
> > You can implement that either using C++0x concepts or SFINAE for
> > expressions.
>
> Either way you need C++0x. But at least extended SFINAE is already
> implemented in usable compilers.
>

The C++03 Standard contains a SFINAE rule reading

> Attempting to perform an invalid conversion in either a template argument expression, or an expres-
sion used in the function declaration.

Interpreted widely, this would consequently mean that sizeof( T
(some_U) ) could be used to check whether you can direct initialize, i
think (after all, if it fails, it would be an invalid conversion in a
template argument expression). If it means only argument expressions
for the template in question, then the expression is still used in the
parameter type of the function type, so the second condition would
fit.

But i think c++1x is much clearer in this situation, totally allowing
the sizeof thing to be used for this.

Mathias Gaunard

unread,
Jun 16, 2009, 1:45:45 PM6/16/09
to
On 16 juin, 01:37, CornedBee <wasti.r...@gmx.net> wrote:

> Either way you need C++0x. But at least extended SFINAE is already
> implemented in usable compilers.

SFINAE for expressions may also be available in C++03 (as a matter of
fact, GCC 4.4 provides the feature both for C++0x and C++03), but is
not clearly mandated by said standard.

0 new messages