C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Template Question
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Suki
Guest





PostPosted: Thu Oct 27, 2005 10:37 am    Post subject: Template Question Reply with quote



Hi,
I'm writing a templated class, and i dont want to use the class
otherthan for some predetermined types, say, int, double etc.

This class has no meaning for typenames other than those few.

=========================
template <class T>
myClass {....} ;

myClass<int> intClass ;
myClass<float> floatClass ;
myClass<char> charClass ;
=========================

The compiler should not complain for the first 2 instantiations, but
should bail out at the 3rd instantiation (charClass). Is there any way
i
can achieve this, using standard c++ or boost.

I've tried explicit template instantiation, (by passing a flag to my
compiler), but in that case, i've to do that for every class

suppose i try to invoke
std::vector <someOtherClass> someVector;

I've to instantiate this also explicitly. (which is a problem for me,
because, I use a lot of standard library, and its a pain for me to
instantiate every time.

Also, if i do the above, i can always instantiate myClass also like
this.

template class myClass <someOtherClass> ;

and which i want to avoid this..

to summarize my question,
is there any way i can restrict the compiler to accept only few type
names for my templated class (i.e., using standard c++ or boost)


Thanks,
Surya


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

Back to top
David Abrahams
Guest





PostPosted: Thu Oct 27, 2005 1:11 pm    Post subject: Re: Template Question Reply with quote



"Suki" <suryakiran.gullapalli (AT) gmail (DOT) com> writes:

Quote:
Hi,
I'm writing a templated class, and i dont want to use the class
otherthan for some predetermined types, say, int, double etc.

This class has no meaning for typenames other than those few.

=========================
template <class T
myClass {....} ;

myClass myClass<float> floatClass ;
myClass<char> charClass ;
=========================

The compiler should not complain for the first 2 instantiations, but
should bail out at the 3rd instantiation (charClass). Is there any way
i
can achieve this, using standard c++ or boost.

Declarative way:

template <class T>
struct myClass_impl
{
...
};

template <class T>
struct myClass;

template<>
myClass<int> : myClass_impl<int>
{};

template<>
myClass<float> : myClass_impl<float>
{};

template<>
myClass<char> : myClass_impl<char>
{};

Imperative way:

#include <boost/mpl/or.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/type_traits/is_same.hpp>

template <class T>
struct myClass
{
BOOST_MPL_ASSERT((boost::mpl::or_<
boost::is_same , boost::is_same<T,float>
, boost::is_same<T,char>
Quote:
));

... // your class implementation here.
};

Quote:
to summarize my question,
is there any way i can restrict the compiler to accept only few type
names for my templated class (i.e., using standard c++ or boost)

HTH,

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

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


Back to top
Catalin Marinas
Guest





PostPosted: Thu Oct 27, 2005 1:12 pm    Post subject: Re: Template Question Reply with quote



"Suki" <suryakiran.gullapalli (AT) gmail (DOT) com> wrote:
Quote:
template <class T
myClass {....} ;
[...]
to summarize my question,
is there any way i can restrict the compiler to accept only few type
names for my templated class (i.e., using standard c++ or boost)

Have a look at Boost typetraits and static_assert. Something like
below would do the job:

template class myClass
{
BOOST_STATIC_ASSERT((boost::is_same<char, T>::value)
Quote:
| (boost::is_same<int, T>::value));
};


--
Catalin

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


Back to top
Tony Delroy
Guest





PostPosted: Thu Oct 27, 2005 1:12 pm    Post subject: Re: Template Question Reply with quote

Hi Surya,

One easy solution is to use a second template, the only purpose of
which is to break My_Class's code when a specialisation doesn't exist.
A lean approach customised to your immediate requirement is:

template <typename T>
class My_Class_Restriction
{
My_Class_Traits(); // note: private constructor
};

template <>
struct My_Class_Restriction<int>
{
};

template <>
struct My_Class_Restriction<double>
{
};

template <typename T>
class My_Class : My_Class_Restriction<T>
{
};

int main()
{
My_Class<int> mci;
My_Class<double> mcd;
My_Class<float> mcf; // breaks
}

But, more generally, you may want to put other things in the additional
class, and consider it a more general "traits" class. You'll find
information about traits on the web or in any half-way-reasonable C++
book.

template <typename T>
struct My_Class_Traits
{
};

template <>
struct My_Class_Traits<int>
{
static inline void is_supported() { }
};

template <>
struct My_Class_Traits<double>
{
static inline void is_supported() { }
};

template <typename T>
class My_Class
{
public:
My_Class()
{
My_Class_Traits<T>::is_supported();
}
};

int main()
{
My_Class<int> mci;
My_Class<double> mcd;
My_Class<float> mcf;
}

Cheers,

Tony


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

Back to top
Greg Herlihy
Guest





PostPosted: Thu Oct 27, 2005 4:39 pm    Post subject: Re: Template Question Reply with quote

Suki wrote:
Quote:
Hi,
I'm writing a templated class, and i dont want to use the class
otherthan for some predetermined types, say, int, double etc.

This class has no meaning for typenames other than those few.

=========================
template <class T
myClass {....} ;

myClass myClass<float> floatClass ;
myClass<char> charClass ;
=========================

The compiler should not complain for the first 2 instantiations, but
should bail out at the 3rd instantiation (charClass). Is there any way
i
can achieve this, using standard c++ or boost.

I've tried explicit template instantiation, (by passing a flag to my
compiler), but in that case, i've to do that for every class

suppose i try to invoke
std::vector <someOtherClass> someVector;

I've to instantiate this also explicitly. (which is a problem for me,
because, I use a lot of standard library, and its a pain for me to
instantiate every time.

Also, if i do the above, i can always instantiate myClass also like
this.

template class myClass <someOtherClass> ;

and which i want to avoid this..

to summarize my question,
is there any way i can restrict the compiler to accept only few type
names for my templated class (i.e., using standard c++ or boost)

First, I would not recommend turning off implicit template
instantiation. The aim here is really not to selectively instantiate -
but to selectively specialize - the template. If the class template is
specialized only for the approved types then only those types will be
able to instantiate the template successfully.

Along these lines, the simplistic solution would be to specialize the
template for each approved type:

template <class T>
class MyClass; // not defined

template <>
class MyClass<int>
{
...
};

template <>
class MyClass<float>
{
...
};

While this technique may be manageable for a few classes and a simple
template, the duplication of the template across each type makes
maintainence inconvenient and error-prone.

Fortunately, C++ allows templates and inheritance to be used together.
And it is this combination that leads to a much more maintainable
solution.

First, declare a base class template that implements the complete
template but whose constructor is protected:

template <class T>
class BaseClass
{
protected:
BaseClass();
public:
... // implement entire template here
};

Next declare (but do not define) the MyClass class template:

template <class T>
class MyClass;

Finally, specialize MyClass for each approved type, as above. Only this
time, the specialization will inherit from the BaseClass template to
obtain the the desired implementation for its type:

template <>
MyClass<int> : public BaseClass<int>
{
public:
MyClass();
...
};

This mechanism prevents anyone from inadvertently instantiating a
MyClass for a non-specialized type and from directly instantiating a
BaseClass for any type.

But one has to wonder whether discouraging the instantiation of
MyClass<char> is really worth going to such lengths. After all, if
MyClass<char> is a plausible specialization, than it probably should be
allowed. On the other hand, if MyClass<char> makes no sense, then
simply relying on the fact that there would never be a good reason to
instantiate MyClass<char> should be a sufficient deterrent. Lastly, it
is always possible to document the template class and list its
supported types. And then the matter would simply rely on each client's
own good judgment.

Greg


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


Back to top
Old Wolf
Guest





PostPosted: Fri Oct 28, 2005 9:07 am    Post subject: Re: Template Question Reply with quote

Suki wrote:
Quote:
Hi,
I'm writing a templated class, and i dont want to use the class
otherthan for some predetermined types, say, int, double etc.

Here's a simple way:

template<typename T> struct Foo;
template<> struct Foo<int> { };
template<> struct Foo<float> { };

template<typename T>
struct X: private Foo<T>
{
};

int main()
{
X<int> a;
X<float> b;
X<char> c;
}


g++ b.cc -o b
b.cc: In instantiation of `X<char>':
b.cc:14: instantiated from here
b.cc:7: error: invalid use of undefined type `struct Foo<char>'


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


Back to top
Carl Barron
Guest





PostPosted: Fri Oct 28, 2005 9:38 am    Post subject: Re: Template Question Reply with quote

Suki <suryakiran.gullapalli (AT) gmail (DOT) com> wrote:

Quote:
Hi,
I'm writing a templated class, and i dont want to use the class
otherthan for some predetermined types, say, int, double etc.

This class has no meaning for typenames other than those few.

=========================
template <class T
myClass {....} ;

myClass myClass<float> floatClass ;
myClass<char> charClass ;
=========================

The compiler should not complain for the first 2 instantiations, but
should bail out at the 3rd instantiation (charClass). Is there any way

The easiest way is to use an additional template that is declared

for all types but only specialized for the desired types as an empty
classs, then MyClass inherits this 'trait class'

template <class T> struct MyClassSupports;
// specialize it for only the desired types

template <> struct MyClassSupports<int>{};
template <> struct MyClassSupports<double>{};

// finally
template <class T>
class MyClass:public MyClassSupports<T>
{
// your class
};

This inheritance has nothing to do with oop it is a method to get
a compiler error if the template argument is different from int or
double.

can be done with boost::enable_if and boost's mpl library if the
# of valid types is fairly large or you don't wnat to pollute your
namespace[s] with extra types soley for compiler checks.

template <class T>
class MyClass:public boost::enable_if
<
boost::mpl::contains
<
boost::mpl::vector T
Quote:
,
boost::mpl::empty_base
::type
{

// your definition
};

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


Back to top
Joshua Lehrer
Guest





PostPosted: Mon Oct 31, 2005 10:48 am    Post subject: Re: Template Question Reply with quote


Carl Barron wrote:
Quote:
The easiest way is to use an additional template that is declared
for all types but only specialized for the desired types as an empty
classs, then MyClass inherits this 'trait class'

template <class T> struct MyClassSupports;
// specialize it for only the desired types

template <> struct MyClassSupports<int>{};
template <> struct MyClassSupports<double>{};

// finally
template <class T
class MyClass:public MyClassSupports {
// your class
};



The problem with this approach (which you and others have pointed out)
is that it allows consumers to hack the protection. The first thing a
user will do, after attempting to instantiate MyClass receiving the error, will be to fully define MyClassSupports<char>,
then to recompile.

Herb Sutter talks about a similar problem in GOTW #76 here:
http://www.gotw.ca/gotw/076.htm

If you really must limit your class to certain types, it is probably
better to do it in the class definition itself, using the static
asserts, and boost mpl, as others have shown. While one could argue
that this imposes what may be an implementation detail (what types are
allowed) on the consumer, I see no other way without sacrificing
security.

joshua lehrer


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


Back to top
lfeiman888@gmail.com
Guest





PostPosted: Tue Nov 01, 2005 9:46 am    Post subject: Re: Template Question Reply with quote

Declarative way:

template <class T>
struct myClass_impl
{
...
};


template <class T>
struct myClass;


template<>
myClass<int> : myClass_impl<int>
{};


template<>
myClass<float> : myClass_impl<float>
{};


template<>
myClass<char> : myClass_impl<char>
{};


But I cannot compile these code under my compiler(vc 2003).Sad
anyone here can???


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

Back to top
kwikius
Guest





PostPosted: Tue Nov 01, 2005 1:02 pm    Post subject: Re: Template Question Reply with quote


[email]lfeiman888 (AT) gmail (DOT) com[/email] wrote:
Quote:
Declarative way:

template <class T
struct myClass_impl
{
...
};


template struct myClass;


template
myClass {};


template
myClass {};


template
myClass {};


But I cannot compile these code under my compiler(vc 2003).Sad
anyone here can???

Each specialisation should have 'struct' after template<>. Is this a
subtle hint from David Abrahams that because we already know what
myClass is that 'struct' is in fact redundant in the above
specialisations ;-)

regards
Andy Little


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


Back to top
kwikius
Guest





PostPosted: Tue Nov 01, 2005 1:02 pm    Post subject: Re: Template Question Reply with quote

Joshua Lehrer wrote:

Quote:
If you really must limit your class to certain types, it is probably
better to do it in the class definition itself, using the static
asserts, and boost mpl, as others have shown. While one could argue
that this imposes what may be an implementation detail (what types are
allowed) on the consumer, I see no other way without sacrificing
security.

'Allowed template parameters' is not an implementation detail. A
template parameter must conform to a concept. Concept is a concise form
of documentation to help user to understand the functionality of a
class or function template.

regards
Andy Little


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


Back to top
Greg Herlihy
Guest





PostPosted: Tue Nov 01, 2005 1:02 pm    Post subject: Re: Template Question Reply with quote


[email]lfeiman888 (AT) gmail (DOT) com[/email] wrote:
Quote:
Declarative way:

template <class T
struct myClass_impl
{
...
};


template struct myClass;


template
myClass {};


template
myClass {};


template
myClass {};


But I cannot compile these code under my compiler(vc 2003).Sad
anyone here can???

Just supply the missing keywords where they are needed:

template struct myClass_impl
{
// ...
};

template <class T>
struct myClass;

template<>
struct myClass<int> : public myClass_impl<int>
{};

template<>
struct myClass<float> : public myClass_impl<float>
{};

template<>
struct myClass<char> : public myClass_impl<char>
{};

Greg


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


Back to top
David Abrahams
Guest





PostPosted: Tue Nov 01, 2005 2:17 pm    Post subject: Re: Template Question Reply with quote

"kwikius" <andy (AT) servocomm (DOT) freeserve.co.uk> writes:

Quote:
lfeiman888 (AT) gmail (DOT) com wrote:
Declarative way:

template <class T
struct myClass_impl
{
...
};


template struct myClass;


template
myClass {};


template
myClass {};


template
myClass {};


But I cannot compile these code under my compiler(vc 2003).Sad
anyone here can???

Each specialisation should have 'struct' after template<>. Is this a
subtle hint from David Abrahams that because we already know what
myClass is that 'struct' is in fact redundant in the above
specialisations Wink

No, it's a subtle hint that I'm as prone to dumb mistakes as anyone
else ;-)

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

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


Back to top
Joshua Lehrer
Guest





PostPosted: Tue Nov 01, 2005 4:46 pm    Post subject: Re: Template Question Reply with quote


kwikius wrote:
Quote:
Joshua Lehrer wrote:

If you really must limit your class to certain types, it is probably
better to do it in the class definition itself, using the static
asserts, and boost mpl, as others have shown. While one could argue
that this imposes what may be an implementation detail (what types are
allowed) on the consumer, I see no other way without sacrificing
security.

'Allowed template parameters' is not an implementation detail. A
template parameter must conform to a concept. Concept is a concise form
of documentation to help user to understand the functionality of a
class or function template.


If that were true, in this case, then the original poster would not
have asked us how to explicitly control the allowable template
parameters. Clearly, the required concept is not enough in this case.
The original poster wants to add an additional restriction. I was
merely pointing out that adding said restriction using inheritence and
template specialization is not as "safe" as using boost::mpl and
compile time asserts.

joshua lehrer


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


Back to top
kwikius
Guest





PostPosted: Thu Nov 03, 2005 10:53 am    Post subject: Re: Template Question Reply with quote


Joshua Lehrer wrote:
Quote:
kwikius wrote:
Joshua Lehrer wrote:

If you really must limit your class to certain types, it is probably
better to do it in the class definition itself, using the static
asserts, and boost mpl, as others have shown. While one could argue
that this imposes what may be an implementation detail (what types are
allowed) on the consumer, I see no other way without sacrificing
security.

'Allowed template parameters' is not an implementation detail. A
template parameter must conform to a concept. Concept is a concise form
of documentation to help user to understand the functionality of a
class or function template.


If that were true, in this case, then the original poster would not
have asked us how to explicitly control the allowable template
parameters.

I dont understand this. The truth of my statement is no way related to
the OP's request.

Quote:
Clearly, the required concept is not enough in this case.
The original poster wants to add an additional restriction. I was
merely pointing out that adding said restriction using inheritence and
template specialization is not as "safe" as using boost::mpl and
compile time asserts.

Users ability to extend the functionality of a library with their own
conforming types is a desirable rather than unsafe feature. If the
library author works in terms of concepts rather than types then the
library is extensible by user by design. Furthermore the error messages
given by compile time asserts in class or function body leads user into
the implementation via recursive template instantion attempts leading
to long error messages, whereas error messages from enable_if ( closest
we can get to true Concept useage in C++) point user to the mistake in
their own source code. In the long error message case I always find
myself scrolling to the end of the error message to find the source
code position. In the second case the desired information is always
available on the first line


regards
Andy Little


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


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.