Re: Making 2 constructor templates that differ only by enable_if;
variadic argument extension to the previous question
Am 05.11.2011 22:10, schrieb Daryle Walker:
You're all familiar with a cross-version constructor template:
template<typename T>
class MyType
{
public:
template<typename U>
MyType( MyType<U> const&o );
//...
};
(Which the compiler will never use as the regular copy constructor by
replacing U with T.) I have two queries.
The first query is that can I have two versions of this method, one
regular one for cross types that can fit within the current version,
and an explicit one for cross types that are too large or something?
Yes, if you can properly express what you describe as "are too large or
something" ;-)
The latter shouldn't be easily converted since some kind of truncation
would need to be done:
template<typename T, unsigned S> // Assume S is never zero
class MyArray
{
public:
MyArray() = default;
Given the below MyType constructors I assume that your template was
intended to me named MyType instead of MyArray (or vice versa).
// Put some kind of enable_if<(R<= S)> in either the template
// parameter part and/or the function parameter part
template<typename U, unsigned R>
MyType( MyType<U,R> const&o );
// Do we have to put some kind of enable_if<(R> S)> magic around
// this one too?
template<typename U, unsigned R>
explicit MyType( MyType<U, R> const&o );
//...
private:
T d_[ S ];
};
To make these two templates constrained, you need to use sfinae based on
non-type template parameters like so:
template <typename U, unsigned R,
typename std::enable_if<(R <= S), bool>::type = true
>
MyType( MyType<U,R> const &o );
template <typename U, unsigned R,
typename std::enable_if<(R > S), bool>::type = true
>
explicit MyType( MyType<U, R> const &o );
This is necessary, because via usual sfinae techniques based on type
templates couldn't distinguish both templates from each other.
The second query is that, given a successful version of MyArray above,
can I modify it so the implicit cross-conversion constructor template
can take a chain of smaller objects:
template<typename T, unsigned S> // Assume S is nonzero
class MyArray
{
public:
MyArray() = default;
// Put some kind of enable_if<!(S % R)> in either the template
// parameter part and/or the function parameter part;
// I have no idea where the "..." bits are supposed to go
template<unsigned R, typename U0, typename ... U>
MyType( MyType<U0,R> const&o0, MyType<U,R> const& ...o );
// Do we have to put some kind of enable_if<(S % R)> magic around
// this one too?
template<typename U, unsigned R>
explicit MyType( MyType<U, R> const&o );
//...
private:
T d_[ S ];
};
The variadic parts don't need to have a special psoition in the list,
because they can be deduced (in contrast to class templates). Oned
possible way of doing so is by writing it as:
template <typename U0, unsigned R,
typename std::enable_if<!(S % R), bool>::type = true,
typename ... U
>
MyType( MyType<U0,R> const &o0, MyType<U,R> const& ...o );
template <typename U, unsigned R,
typename std::enable_if<(S % R), bool>::type = true
>
explicit MyType( MyType<U, R> const &o );
The first constructor template takes at least one argument so it won't
be confused with the default constructor, and that it is the only(!)
way of specifying R. (All constructor template parameters must be
implied.) If this can be done, is there a way to limit the number of
parameters, including U0, to (S / R) at compile time?
I don't see a problem for doing this as part of the constructor
templates constraints as well, just extend the enable_if test above.
And can this system work if we let
also let R (along with U) vary for all objects in a list? (We would
need to sum up all the R values for a length check.)
I'm not sure whether I really understand this particular question, but
it sounds as if this could work as well.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]