From: pfultz2 on
I am trying to use this code as a parameter like this:

template<typename T>
void takesCollection(typename Collection<T>::Type col)
{

}

using this class here:
template<typename C, typename Enable = void>
class Collection
{

};

template<typename C>
class Collection<C, REQUIRES(is_collection<C>)>
{
public:
typedef C Type;
};

but it says that cant find the overload when i call it like this:
void takesCollection(var->GetCollection())
{
}
Is this too complicated for the compiler to figure out?? Or is it
because im using a an rvalue?
Also is there a way i can use a template to always give me a reference
either const, lvalue or rvalue. So instead of calling three overloads
like this:
template<typename T>
void foo(const T& x);
template<typename T>
void foo(T& x);
template<typename T>
void foo(T && x);
instead i could just write:
template<typename T>
void foo(typename ReferenceType<T>::Type x);
and it would create the necessary overloads?? or maybe i need to use
nested templates?? any ideas would be great.
thanks

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Bart van Ingen Schenau on
On Dec 12, 11:07 am, pfultz2 <pful...(a)yahoo.com> wrote:
> I am trying to use this code as a parameter like this:
>
> template<typename T>
> void takesCollection(typename Collection<T>::Type col)

Warning: T is used only in a non-deduced context. The only way to call
this function is by explicitly specifying the type to be used for T.

> {
>
> }
>
> using this class here:
> template<typename C, typename Enable = void>
> class Collection
> {
>
> };
>
> template<typename C>
> class Collection<C, REQUIRES(is_collection<C>)>
> {
> public:
> typedef C Type;
> };
>
> but it says that cant find the overload when i call it like this:
> void takesCollection(var->GetCollection())
> {}
>
> Is this too complicated for the compiler to figure out?? Or is it
> because im using a an rvalue?

It is too complicated for the compiler, because the compiler can't
know if there is exactly one type T for which Collection<T>::Type
resolves to the provided type.

> Also is there a way i can use a template to always give me a reference
> either const, lvalue or rvalue. So instead of calling three overloads
> like this:
> template<typename T>
> void foo(const T& x);
> template<typename T>
> void foo(T& x);
> template<typename T>
> void foo(T && x);
> instead i could just write:
> template<typename T>
> void foo(typename ReferenceType<T>::Type x);
> and it would create the necessary overloads?? or maybe i need to use
> nested templates?? any ideas would be great.

If my understanding of r-value references in the context of templates
is correct, then it should be sufficient to have the single function
template <typename T>
void foo(T&& x);

If the actual argument a (non-const) l-value, the instantiated
function will accept a (non-const) l-value reference.
If the actual argument is a const l-value, the instantiated function
will accept a const l-value reference.
If the actual argument is an r-value, the instantiated function will
accept an r-value reference.

Only if you want the overloads to behave differently, you have to
specify separate overloads.

> thanks
>

Bart v Ingen Schenau


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: SG on
On 15 Dez., 01:58, pfultz2 <pful...(a)yahoo.com> wrote:
> So there is no way to limit the types that are given to a function
> without using enable_if. That is i cant write a function call like
> this:
> template<typename T>
> void foo(add_reference<T>::type x);
> and it will only accept a reference type for the function??

Right. In this case Template Argument Deduction won't work because the
compiler is not able to figure out T on its own -- no matter how
simple the definition of add_reference may look like. Here's a counter
example that has little to do with "add_reference" except for the
name:

template<typename T>
struct add_reference { typedef T type; };

template<>
struct add_reference<int> { typedef double type; };

So, what is T if add_referemce<T>::type is double? In this case
T=double and T=int works. Which choice is the correct one? The problem
here is that it is (a) difficult to determine the set of possible Ts
and (b) there's no way to know what T is the correct one if the set
contains more than one type.

Cheers,
SG


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: pfultz2 on
On Dec 15, 10:35 am, SG <s.gesem...(a)gmail.com> wrote:
> On 15 Dez., 01:58, pfultz2 <pful...(a)yahoo.com> wrote:
>
> > So there is no way to limit the types that are given to a function
> > without using enable_if. That is i cant write a function call like
> > this:
> > template<typename T>
> > void foo(add_reference<T>::type x);
> > and it will only accept a reference type for the function??
>
> Right. In this case Template Argument Deduction won't work because the
> compiler is not able to figure out T on its own -- no matter how
> simple the definition of add_reference may look like. Here's a counter
> example that has little to do with "add_reference" except for the
> name:
>
> template<typename T>
> struct add_reference { typedef T type; };
>
> template<>
> struct add_reference<int> { typedef double type; };
>
> So, what is T if add_referemce<T>::type is double? In this case
> T=double and T=int works. Which choice is the correct one? The problem
> here is that it is (a) difficult to determine the set of possible Ts
> and (b) there's no way to know what T is the correct one if the set
> contains more than one type.

So if i wanted to only accept reference i could use an enable_if
instead, right?
I would do this instead:
template<typename T>
void foo(T x, typename enable_if<is_reference<T>>::type* = 0);
This would only accept a reference type? But is there an easier way to
create a set of types and have the function only accept those set of
types, maybe something like this:
template<typename T>
void foo(T x, typename enable_if<is_same<T, typename
add_reference<T>::type>::type* = 0);
But if i wanted some types to be say reference and maybe some types to
be pass by value, this still might be a little complicated, I just
wish i could direct the compiler how to pass it in or give a little
hint to the compiler how it should be passed in.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]