From: Chris Fairles on
Below is some code illustrating the wrong way to do what I'd like to
do. I have a class "A" with function "void f(int,int)" and class "B"
without that function. Is there a way to construct a traits-like
class, Q, that contains a constant expression (Q<T>::value) that
evaluates to true if some class T has the function "void f
(int,int)" ?

Pretend A and B cannot be changed. You only have Q to work with.

struct A {
void f (int,int){}
};

struct B{};

template <class T,class F=void>
struct Q {
enum{value=false};
};

template<class T>
struct Q<T,void(T::*)(int,int)> {
enum{value=true};
};

int main() {
if( Q<A>::value ) {cout << "A";}
if( !Q<B>::value ){cout << "B";}
}

I'd like this to output "AB". I've tried playing around with
boost::enable_if and boost::function_traits but have not come up with
a solution.

The above code is a trivial case. The real case is, I'm trying to come
up with a "is_serializable" type trait (Q) so that an I/O "write"-like
function does something special for non-serializable classes (and just
does normal serialization for those that are). Every serializable
class has this function defined (as a mem func):
template <typename Archive>
void serialize(Archive &, const unsigned int);

If I could add a typedef to each serializable class, no problem. I
could even make a typelist of all serializable classes and use a
visitor/enable_if or something but I'd like to consider these last
resorts.

Thanks for the help,
Chris


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

From: KDroben on
On 21 juil, 09:36, Chris Fairles <chris.fair...(a)gmail.com> wrote:
> Below is some code illustrating the wrong way to do what I'd like to
> do. I have a class "A" with function "void f(int,int)" and class "B"
> without that function. Is there a way to construct a traits-like
> class, Q, that contains a constant expression (Q<T>::value) that
> evaluates to true if some class T has the function "void f
> (int,int)" ?
>
> Pretend A and B cannot be changed. You only have Q to work with.
>
> struct A {
> void f (int,int){}
>
> };
>
> struct B{};
>
> template <class T,class F=void>
> struct Q {
> enum{value=false};
>
> };
>
> template<class T>
> struct Q<T,void(T::*)(int,int)> {
> enum{value=true};
>
> };
>
> int main() {
> if( Q<A>::value ) {cout << "A";}
> if( !Q<B>::value ){cout << "B";}
>
> }
>
> I'd like this to output "AB". I've tried playing around with
> boost::enable_if and boost::function_traits but have not come up with
> a solution.
>
> The above code is a trivial case. The real case is, I'm trying to come
> up with a "is_serializable" type trait (Q) so that an I/O "write"-like
> function does something special for non-serializable classes (and just
> does normal serialization for those that are). Every serializable
> class has this function defined (as a mem func):
> template <typename Archive>
> void serialize(Archive &, const unsigned int);
>
> If I could add a typedef to each serializable class, no problem. I
> could even make a typelist of all serializable classes and use a
> visitor/enable_if or something but I'd like to consider these last
> resorts.
>
> Thanks for the help,
> Chris

Check this article :
http://www.codeproject.com/useritems/Detector.asp

I think it covers what you are trying to do.


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

From: Alp Mestan on
Chris Fairles wrote:
> Below is some code illustrating the wrong way to do what I'd like to
> do. I have a class "A" with function "void f(int,int)" and class "B"
> without that function. Is there a way to construct a traits-like
> class, Q, that contains a constant expression (Q<T>::value) that
> evaluates to true if some class T has the function "void f
> (int,int)" ?
>
> Pretend A and B cannot be changed. You only have Q to work with.
>
> struct A {
> void f (int,int){}
> };
>
> struct B{};
>
> template <class T,class F=void>
> struct Q {
> enum{value=false};
> };
>
> template<class T>
> struct Q<T,void(T::*)(int,int)> {
> enum{value=true};
> };
>
> int main() {
> if( Q<A>::value ) {cout << "A";}
> if( !Q<B>::value ){cout << "B";}
> }
>
> I'd like this to output "AB". I've tried playing around with
> boost::enable_if and boost::function_traits but have not come up with
> a solution.
>
> The above code is a trivial case. The real case is, I'm trying to come
> up with a "is_serializable" type trait (Q) so that an I/O "write"-like
> function does something special for non-serializable classes (and just
> does normal serialization for those that are). Every serializable
> class has this function defined (as a mem func):
> template <typename Archive>
> void serialize(Archive &, const unsigned int);
>
> If I could add a typedef to each serializable class, no problem. I
> could even make a typelist of all serializable classes and use a
> visitor/enable_if or something but I'd like to consider these last
> resorts.
>
> Thanks for the help,
> Chris
>
>

It appears that you must give explicitly what is 'F' in your template,
as follows :

int main() {
if( Q<A,void(A::*)(int,int)>::value ) {cout << "A";}
if( !Q<B>::value ){cout << "B";}
return 0;
}

It is normal, because the compiler waits two types. When there isn't any
second type given, it considers voice instead.

The only way to get what you want is to pass your parameters to a
function which would auto-detect (template arguments deduction is for
functions only) that the function is a member function of T.




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

From: Carl Barron on
In article <1184979526.199331.181740(a)q75g2000hsh.googlegroups.com>,
Chris Fairles <chris.fairles(a)gmail.com> wrote:

> Below is some code illustrating the wrong way to do what I'd like to
> do. I have a class "A" with function "void f(int,int)" and class "B"
> without that function. Is there a way to construct a traits-like
> class, Q, that contains a constant expression (Q<T>::value) that
> evaluates to true if some class T has the function "void f
> (int,int)" ?
>
> Pretend A and B cannot be changed. You only have Q to work with.
>
> struct A {
> void f (int,int){}
> };
>
> struct B{};
>
> template <class T,class F=void>
> struct Q {
> enum{value=false};
> };
>
> template<class T>
> struct Q<T,void(T::*)(int,int)> {
> enum{value=true};
> };
>
> int main() {
> if( Q<A>::value ) {cout << "A";}
> if( !Q<B>::value ){cout << "B";}
> }
>
> I'd like this to output "AB". I've tried playing around with
> boost::enable_if and boost::function_traits but have not come up with
> a solution.
>
> The above code is a trivial case. The real case is, I'm trying to come
> up with a "is_serializable" type trait (Q) so that an I/O "write"-like
> function does something special for non-serializable classes (and just
> does normal serialization for those that are). Every serializable
> class has this function defined (as a mem func):
> template <typename Archive>
> void serialize(Archive &, const unsigned int);
>
> If I could add a typedef to each serializable class, no problem. I
> could even make a typelist of all serializable classes and use a
> visitor/enable_if or something but I'd like to consider these last
> resorts.
>
See boost::mpl

template <class T>
struct is_serializable:boost::mpl::contains
<
boost::mpl::vector<types_to_serialize_comma_seperated>,
T
>
{
};

this has a nested typedef typedef something type;
where something is either boost::mpl::true_ or boost::mpl::false_,
with obvious meanings. type also has an operator bool() const,
and a static const bool which return /is the boolean value true or
false accordingly.

so you can overload for boost::mpl::true_ and boost::mpl_false
or just add a boolean value that defaults to
is_serializable<T>::type::value.

template <class T>
void my_function(const T &a,bool which=is_serializable<T>::type::value)
{
check the value of which at runtime.
}

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

From: Greg Herlihy on
On Jul 21, 12:36 am, Chris Fairles <chris.fair...(a)gmail.com> wrote:
> Below is some code illustrating the wrong way to do what I'd like to
> do. I have a class "A" with function "void f(int,int)" and class "B"
> without that function. Is there a way to construct a traits-like
> class, Q, that contains a constant expression (Q<T>::value) that
> evaluates to true if some class T has the function "void f
> (int,int)" ?
>
> Pretend A and B cannot be changed. You only have Q to work with.
>
> struct A {
> void f (int,int){}
>
> };
>
> struct B{};
>
> template <class T,class F=void>
> struct Q {
> enum{value=false};
>
> };
>
> template<class T>
> struct Q<T,void(T::*)(int,int)> {
> enum{value=true};
>
> };
>
> int main() {
> if( Q<A>::value ) {cout << "A";}
> if( !Q<B>::value ){cout << "B";}
>
> }
>
> I'd like this to output "AB". I've tried playing around with
> boost::enable_if and boost::function_traits but have not come up with
> a solution.

How about:

#include <iostream>

template <class T, void (T::*)(int, int) >
struct mf_bind
{
typedef T type;
};

template <class T1, class T2>
struct has_f
{
static const bool value = false;
};

template <class T>
struct has_f<T, typename mf_bind<T, &T::f>::type>
{
static const bool value = true;
};

template <class T>
struct Q
{
static const bool value = has_f<T, T>::value;
};

// A and B test classes

struct A
{
void f (int,int){}
};

struct B{};

using std::cout;

int main()
{
if( Q<A>::value ) {cout << "A";}
if( !Q<B>::value ){cout << "B";}
}

Program Output:

AB

Greg



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