473,794 Members | 2,774 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Template function specialization/overloading

I am facing the following scenario: I have a class 'A', that implements
some concept C -- but we know this, not because A inherits from a
virtual class 'C', but only because a trait tell us so:

class A {};

template <typename T>
struct Is_C
{
static const bool value = false;
};

template <>
struct Is_C<A>
{
static const bool value = true;
};
What I would like to do is, given an instance 'a' of A, call a function
'foo(a)' that would have specific code for class A -- and have default
code for other classes.

The following

template < typename T >
void foo(T t)
{
if (Is_C<T>::value )
{
/* ... */
}
else
{
/* ... */
}
}

would work, but then, it is not extensible to another trait 'Is_D'
unless I modify the function foo. Ideally I would have a function foo
for the general case (corresponding to the 'else') and as many
functions foo for all the different tests, but I am not sure how to do
that. I would like to use the boost::enable_i f, but if I use function
overloading, I need to have a disable_if in my 'general case' foo for
each 'specialized' foo:

// General case
template < typename T >
typename disable_if<Is_C <T> >::type // This has to be modified if
another foo is added
foo(T t)
{
/* ... */
}

// Specialization for concept C
template < typename T >
typename enable_if<Is_C< T> >::type
foo(T t)
{
/* ... */
}

I would really appreciate any suggestion for this problem.

Thanks

B.

Jul 23 '05 #1
11 2491
ga*******@voila .fr wrote:
I am facing the following scenario: I have a class 'A', that implements
some concept C -- but we know this, not because A inherits from a
virtual class 'C', but only because a trait tell us so:

class A {};

template <typename T>
struct Is_C
{
static const bool value = false;
};

template <>
struct Is_C<A>
{
static const bool value = true;
};
What I would like to do is, given an instance 'a' of A, call a function
'foo(a)' that would have specific code for class A -- and have default
code for other classes.

The following

template < typename T >
void foo(T t)
{
if (Is_C<T>::value )
{
/* ... */
}
else
{
/* ... */
}
}

would work, but then, it is not extensible to another trait 'Is_D'
unless I modify the function foo. Ideally I would have a function foo
for the general case (corresponding to the 'else') and as many
functions foo for all the different tests, but I am not sure how to do
that. I would like to use the boost::enable_i f, but if I use function
overloading, I need to have a disable_if in my 'general case' foo for
each 'specialized' foo:

// General case
template < typename T >
typename disable_if<Is_C <T> >::type // This has to be modified if
another foo is added
foo(T t)
{
/* ... */
}

// Specialization for concept C
template < typename T >
typename enable_if<Is_C< T> >::type
foo(T t)
{
/* ... */
}

I would really appreciate any suggestion for this problem.
Interesting problem. Of course, the first think I want to say is that
you're confusing yourself and others calling your "traits" 'Is_C' or
'Is_D'. Apparently your class A _isn't_ C or D, otherwise inheritance
should work just fine. You should name your concept as it is, something
like 'implements_C' or 'implements_D'.

Anyway... I thought of providing the helper for your 'foo':
------------------------------------------------------------------------
#include <iostream>

template<class T> struct implements_C { enum { value = 0 }; };

template<class T, bool b> struct foo_helper {
static void foo(T t)
{
std::cout << "Generic foo\n";
}
};

template<class T> struct foo_helper<T, true> {
static void foo(T t)
{
std::cout << "'true'-specific foo\n";
}
};

template<class T> void foo(T t)
{
foo_helper<T, implements_C<T> ::value>::foo(t );
}

class A {};
class B {};

template<> struct implements_C<A> { enum { value = 1 }; };

int main()
{
A a;
foo(a);
B b;
foo(b);
}
------------------------------------------------------------------------

Now, if you need to add another "policy", the 'foo_helper', which does
the actual work, shouldn't change. What you change is the 'foo':
template<class T> void foo(T t)
{
foo_helper<T,
implements_C<T> ::value || implements_D<T> ::value::foo(t);

}

Here is amended code with two policies:
------------------------------------------------------------------------
#include <iostream>

template<class T> struct implements_C { enum { value = 0 }; };
template<class T> struct implements_D { enum { value = 0 }; };

template<class T, bool b> struct foo_helper {
static void foo(T t)
{
std::cout << "Generic foo\n";
}
};

template<class T> struct foo_helper<T, true> {
static void foo(T t)
{
std::cout << "'true'-specific foo\n";
}
};

template<class T> void foo(T t)
{
foo_helper<T, implements_C<T> ::value || implements_D<T> ::value >::foo(t);
}

class A {};
class B {};
class AB {};
class C {};

template<> struct implements_C<A> { enum { value = 1 }; };
template<> struct implements_D<B> { enum { value = 1 }; };
template<> struct implements_C<AB > { enum { value = 1 }; };
template<> struct implements_D<AB > { enum { value = 1 }; };

int main()
{
A a;
foo(a);
B b;
foo(b);
AB ab;
foo(ab);
C c;
foo(c);
}
--------------------------------------------------------------------

HTH

V
Jul 23 '05 #2
Thanks for your answer. However, my problem is slightly different --
let me explain further. I want to leave the possibility open to add a
third function foo in case somebody comes up with another concept D for
which foo should be implemented differently. E.g:

// General case
template < typename T >
// the following line has been modify when third foo was added
typename disable_if<impl ements_C<T> || implements_D<T> >::type
foo(T t)
{
/* ... */
}

// Specialization for concept C
template < typename T >
typename enable_if<imple ments_C<T> >::type
foo(T t)
{
/* ... */
}

// Specialization for concept D
template < typename T >
typename enable_if<imple ments_D<T> >::type
foo(T t)
{
/* ... */
}
One could generalize your idea of helper functions by replacing a bool
by an integer, but I don't like the idea of having to modify the helper
function -- in that sense, I am not sure what benefits come from you
approach compared to the previous collection of functions. Ideally
somebody should be able to add a 'foo' without having to modify the
remaining of the code.

Jul 23 '05 #3
ga*******@voila .fr wrote:
Thanks for your answer. However, my problem is slightly different --
let me explain further. I want to leave the possibility open to add a
third function foo in case somebody comes up with another concept D for
which foo should be implemented differently.

What you need could be achieved by adding a 'tag' inside your traits
class. For example, here's some pseudocode:

struct ATag { };
struct BTag { };
struct CTag { };

template <typename TYPE>
struct Traits;

class SomeClassThatHa sATrait { ... };
class SomeClassThatHa sBTrait { ... };
class SomeClassThatHa sCTrait { ... };

template <>
struct Traits<SomeClas sThatHasATrait> { typedef ATag Tag; };

template <>
struct Traits<SomeClas sThatHasBTrait> { typedef BTag Tag; };

template <>
struct Traits<SomeClas sThatHasCTrait> { typedef CTag Tag; };

template <typename TYPE>
void foo(TYPE object, ATag)
{
... code for types that have A trait ....
}

template <typename TYPE>
void foo(TYPE object, BTag)
{
... code for types that have B trait ....
}

template <typename TYPE>
void foo(TYPE object, CTag)
{
... code for types that have C trait ....
}

template <typename TYPE>
void foo(TYPE object)
{
typedef typename Traits<TYPE>::T ag Tag;
foo(object, Tag());
}

-----------------------------------------

Now, when you want to add a new 'D' trait, all you have to do is define
a tag for it:

struct DTag { };

Define some class that has the D trait:

class SomeClassThatHa sDTrait { ... };

template <>
struct Traits<SomeClas sThatHasDTrait> { typedef DTag Tag; };

Next, define a foo function for classes that have the D trait:

template <typename TYPE>
void foo(TYPE object, DTag)
{
... code for types that have C trait ....
}
Hope this helps,
-shez-

Jul 23 '05 #4
Shezan Baig wrote:
ga*******@voila .fr wrote:
Thanks for your answer. However, my problem is slightly different --
let me explain further. I want to leave the possibility open to add a
third function foo in case somebody comes up with another concept D for
which foo should be implemented differently.
What you need could be achieved by adding a 'tag' inside your traits
class. For example, here's some pseudocode:

struct ATag { };
struct BTag { };
struct CTag { };

template <typename TYPE>
struct Traits;


This has to be somehow defined for "any other type TYPE".

class SomeClassThatHa sATrait { ... };
class SomeClassThatHa sBTrait { ... };
class SomeClassThatHa sCTrait { ... };
[...]

template <typename TYPE>
void foo(TYPE object)
{
typedef typename Traits<TYPE>::T ag Tag;
And it's not going to compile if there is no 'Tag' defined. You'll
need to have some kind of "default traits" and the corresponding
"default" behaviour.
foo(object, Tag());
}


V
Jul 23 '05 #5


Victor Bazarov wrote:
Shezan Baig wrote:
ga*******@voila .fr wrote:
Thanks for your answer. However, my problem is slightly different --
let me explain further. I want to leave the possibility open to add a
third function foo in case somebody comes up with another concept D for
which foo should be implemented differently.


What you need could be achieved by adding a 'tag' inside your traits
class. For example, here's some pseudocode:

struct ATag { };
struct BTag { };
struct CTag { };

template <typename TYPE>
struct Traits;


This has to be somehow defined for "any other type TYPE".

class SomeClassThatHa sATrait { ... };
class SomeClassThatHa sBTrait { ... };
class SomeClassThatHa sCTrait { ... };
[...]

template <typename TYPE>
void foo(TYPE object)
{
typedef typename Traits<TYPE>::T ag Tag;


And it's not going to compile if there is no 'Tag' defined. You'll
need to have some kind of "default traits" and the corresponding
"default" behaviour.


Yeap. If you need default behaviour, then instead of:

template <typename TYPE>
struct Traits;

you need to do:

template <typename TYPE>
struct Traits {
typedef DefaultTag Tag;
};

and create a corresponding foo(TYPE, DefaultTag) function.

-shez-

Jul 23 '05 #6
This is indeed in the spirit of what I was looking for. It is still one
footstep of being exactly what I need though, because it doesn't reuse
the information that was already there in the implements_X classes. In
the first place I thought that this problem is hard precisely because
the information is not encoded in the form of class types -- and your
solution is exactly going manually from one form to the other. Is there
a way to go without having to rewrite all these traits specialization?

B.

Jul 23 '05 #7
ga*******@voila .fr wrote:
This is indeed in the spirit of what I was looking for. It is still one
footstep of being exactly what I need though, because it doesn't reuse
the information that was already there in the implements_X classes. In
the first place I thought that this problem is hard precisely because
the information is not encoded in the form of class types -- and your
solution is exactly going manually from one form to the other. Is there
a way to go without having to rewrite all these traits specialization?

B.

Specialize the trait. Its hardly much typing! And even less if you
just copy&paste :)

-shez-

Jul 23 '05 #8
That's not that simple. Suppose 'foo' now depends on three parameters,
and I want to specialized foo when all three parameters have a true
std::numeric_li mits<>::is_spec ialized. There is no copy-pasting
possible. And can you just imagine the number of specialized traits I
would have to type?

Jul 23 '05 #9
gao_bo...@voila .fr wrote:
That's not that simple. Suppose 'foo' now depends on three parameters,
and I want to specialized foo when all three parameters have a true
std::numeric_li mits<>::is_spec ialized. There is no copy-pasting
possible. And can you just imagine the number of specialized traits I
would have to type?

All you need is one tag per overloaded 'foo'. And one specialization
per 'TYPE' that 'foo' can operate on.

Jul 23 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

17
6868
by: Paul MG | last post by:
Hi Template partial specialization always seems like a fairly straightforward concept - until I try to do it :). I am trying to implement the input sequence type (from Stroustrup section 18.3.1, 'Iseq'). I want the version for containers that he gives, but also to provide a specialization for construction from a pair<It,It> (eg because that is returned by equal_range()).
2
5780
by: Jeff | last post by:
/* -------------------------------------------------------------------------- Hello, I was experimenting with class templates and specializing member functions and came across a simple problem which I can't figure out. I have a simple class C with 2 template member objects, and a function print() that prints the value of these objects. I defined a specialization of print() for C<string, char> which is called correctly. Then I wanted...
8
6741
by: Massimiliano Alberti | last post by:
Can I specialize a template function in a subclass without overriding it? (the main template function is defined in a base class). Now I'm doing something like that: (in base class) template<class X> void myfunc(X par1) { } (in derived class) template<class X>
5
6590
by: Levent | last post by:
Hi, Why doesn't this work? (tried with gcc 3.3.3 and VC++ 7.1): #include <iostream> template<class T, unsigned N> struct Foo { void func(); }; template<class T, unsigned N>
2
3690
by: Michael Stembera | last post by:
Here is a very simple piece of code to repro this bug. template<typename T, int N> inline bool foo( void ) { return true; } template<typename T> inline bool foo<T, 1>( void ) { return false;
6
5017
by: flopbucket | last post by:
Could someone explain to me what the difference is between function template specialization and function overloading? I guess overloading can change the number of parameters, but otherwise they seem very similar to me - i.e. they both provide specialized functions for depending on the parameter types. Thanks
4
3356
by: stinos | last post by:
Hi All! suppose a class having a function for outputting data somehow, class X { template< class tType > void Output( const tType& arg ) { //default ToString handles integers/doubles
8
1950
by: mattias.nissler | last post by:
Hi! Here is a problem I ran into at work. The following example doesn't compile on gcc-4.1: struct cons_end {}; template<typename U,typename Vstruct cons { U elem; V tail;
13
6599
by: mike b | last post by:
Hello everyone, thanks in advance for your help. I'm new to C++ templates and have run into some issues using member function templates. I have a shared library containing templates that I'm trying to use from an executable, compile using gcc 4.1.2. Everything works fine until I try specializing one of the static member function templates in a non-template class. I have a feeling I'm messing up something obvious so before I post a...
0
9672
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
10435
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10163
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10000
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9037
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7538
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6779
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5563
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
3
2920
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.