By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,149 Members | 1,051 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,149 IT Pros & Developers. It's quick & easy.

Template Question

P: n/a
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! ]

Oct 27 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
Suki wrote:
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.

[snip]

What about:
template < typename bad_class >
struct bad_class_flag;

template <>
struct bad_class_flag<int> {};

template <>
struct bad_class_flag<float> {};

template < typename T >
class my_class : bad_class_flag<T> {

// my stuff goes here;

}; // my_class
int main ( void ) {
my_class<int> int_obj;
my_class<float> float_obj;
my_class<char> char_obj; // triggers an error
}

Best

Kai-Uwe Bux
Oct 27 '05 #2

P: n/a
"Suki" <su*******************@gmail.com> writes:
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.
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<T,int>
, boost::is_same<T,float>
, boost::is_same<T,char>));
... // your class implementation here.
};
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! ]

Oct 27 '05 #3

P: n/a
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! ]

Oct 27 '05 #4

P: n/a
Suki wrote:
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)


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! ]

Oct 27 '05 #5

P: n/a
Suki wrote:
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! ]

Oct 28 '05 #6

P: n/a
Suki <su*******************@gmail.com> wrote:
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
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<int,double>,
T, 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! ]

Oct 28 '05 #7

P: n/a
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).:(
anyone here can???
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Nov 1 '05 #8

P: n/a

lf********@gmail.com wrote:
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).:(
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! ]

Nov 1 '05 #9

P: n/a

lf********@gmail.com wrote:
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).:(
anyone here can???


Just supply the missing keywords where they are needed:

template <class T>
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! ]

Nov 1 '05 #10

P: n/a
"kwikius" <an**@servocomm.freeserve.co.uk> writes:
lf********@gmail.com wrote:
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).:(
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 ;-)


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! ]

Nov 1 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.