Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Explicit specialization of member template when type is anothertemplate type.

Reply
Thread Tools

Explicit specialization of member template when type is anothertemplate type.

 
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      12-05-2008
Here is a program, it looks weird but it models what I'm trying to do.
In this program:

- "Object" is just some example type.
- "Container" holds a single item of some type, but provides access
access to a copy of that object only via a nested class
Container::ContainedItem.

=== BEGIN ===

// An example object with a member function.
class Object {
public:
void function () const { }
};

template <typename T> class Container {
private:
T data_; // Container's instance of the data.
public:
// This just wraps an item.
class ContainedItem {
private:
T item_; // Some copy of the data.
public:
explicit ContainedItem (const T &item) : item_(item) { }
const T * getItem () const; // This gets the copy.
};
// Get via ContainedItem.
ContainedItem getData () const { return ContainedItem(data_); }
// Set value directly.
void setData (const T &data) { data_ = data; }
};

// Generic template implementation.
template <typename T>
const T * Container<T>::ContainedItem::getItem () const {
return &item_;
}

=== END ===


Now, my problem is very specific: When T is an arbitrary type I want
Container<T>::ContainedItem::getItem() to return a const T *, just
like it already does. However, when T specifically is a
boost::shared_ptr<X>, I want Container<T>::ContainedItem::getItem() to
return a const X *, not a const T *. For example:


=== BEGIN ===

#include <boost/shared_ptr.hpp>
using boost::shared_ptr;

int main () {
Container<Object> x;
Container<shared_ptr<Object> > y;
x.setData(Object()); // i want this
y.setData(shared_ptr<Object>()); // i want this
x.getData().getItem()->function(); // i want this
y.getData().getItem()->get()->function(); // don't want this!
//y.getData().getItem()->function(); // i want this instead!
}

=== END ===


Basically, as shown above, for shared_ptr<X> template types, I don't
want the extra "get()" in there (boost::shared_ptr<X> does not define
a conversion to X*). Is there some way I can make an explicit
specialization for getItem(), for type T = boost::shared_ptr<X>, and
have it return a const X * (it would return "item_.get()" instead of
"&item_")? I can't figure out the syntax for it, if it's possible.

Is there some other solution instead? It's not that I don't want to
type "get()", it's that I want Container<X> and
Container<shared_ptr<X> > to have getData().getItem() return the same
type for both.

Thanks,
Jason
 
Reply With Quote
 
 
 
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      12-05-2008
On Dec 5, 12:25*am, "jason.cipri...@gmail.com"
<jason.cipri...@gmail.com> wrote:
> Here is a program, it looks weird but it models what I'm trying to do.
> In this program:
>
> * - "Object" is just some example type.
> * - "Container" holds a single item of some type, but provides access
> access to a copy of that object only via a nested class
> Container::ContainedItem.
>
> === BEGIN ===
>
> // An example object with a member function.
> class Object {
> public:
> * * * * void function () const { }
>
> };
>
> template <typename T> class Container {
> private:
> * * * * T data_; // Container's instance of the data.
> public:
> * * * * // This just wraps an item.
> * * * * class ContainedItem {
> * * * * private:
> * * * * * * * * T item_; // Some copy of the data.
> * * * * public:
> * * * * * * * * explicit ContainedItem (const T &item) : item_(item) { }
> * * * * * * * * const T * getItem () const; // This gets the copy.
> * * * * };
> * * * * // Get via ContainedItem.
> * * * * ContainedItem getData () const { return ContainedItem(data_); }
> * * * * // Set value directly.
> * * * * void setData (const T &data) { data_ = data; }
>
> };
>
> // Generic template implementation.
> template <typename T>
> const T * Container<T>::ContainedItem::getItem () const {
> * * * * return &item_;
>
> }
>
> === END ===
>
> Now, my problem is very specific: When T is an arbitrary type I want
> Container<T>::ContainedItem::getItem() to return a const T *, just
> like it already does. However, when T specifically is a
> boost::shared_ptr<X>, I want Container<T>::ContainedItem::getItem() to
> return a const X *, not a const T *. For example:
>
> === BEGIN ===
>
> #include <boost/shared_ptr.hpp>
> using boost::shared_ptr;
>
> int main () {
> * * * * Container<Object> x;
> * * * * Container<shared_ptr<Object> > y;
> * * * * x.setData(Object()); // i want this
> * * * * y.setData(shared_ptr<Object>()); // i want this
> * * * * x.getData().getItem()->function(); // i want this
> * * * * y.getData().getItem()->get()->function(); // don't want this!
> * * * * //y.getData().getItem()->function(); // i want this instead!
>
> }
>
> === END ===
>
> Basically, as shown above, for shared_ptr<X> template types, I don't
> want the extra "get()" in there (boost::shared_ptr<X> does not define
> a conversion to X*). Is there some way I can make an explicit
> specialization for getItem(), for type T = boost::shared_ptr<X>, and
> have it return a const X * (it would return "item_.get()" instead of
> "&item_")? I can't figure out the syntax for it, if it's possible.
>
> Is there some other solution instead? It's not that I don't want to
> type "get()", it's that I want Container<X> and
> Container<shared_ptr<X> > to have getData().getItem() return the same
> type for both.



I'm sorry, I mistitled this post. Originally I had been playing with
member templates and that's what I had on my mind when I typed the
subject. Should probably read "template member" I guess, or something.

Jason
 
Reply With Quote
 
 
 
 
Triple-DES
Guest
Posts: n/a
 
      12-05-2008
On 5 Des, 06:25, "jason.cipri...@gmail.com" <jason.cipri...@gmail.com>
wrote:

> === BEGIN ===
>
> // An example object with a member function.
> class Object {
> public:
> * * * * void function () const { }
>
> };
>
> template <typename T> class Container {
> private:
> * * * * T data_; // Container's instance of the data.
> public:
> * * * * // This just wraps an item.
> * * * * class ContainedItem {
> * * * * private:
> * * * * * * * * T item_; // Some copy of the data.
> * * * * public:
> * * * * * * * * explicit ContainedItem (const T &item) : item_(item) { }
> * * * * * * * * const T * getItem () const; // This gets the copy.
> * * * * };
> * * * * // Get via ContainedItem.
> * * * * ContainedItem getData () const { return ContainedItem(data_); }
> * * * * // Set value directly.
> * * * * void setData (const T &data) { data_ = data; }
>
> };
>
> // Generic template implementation.
> template <typename T>
> const T * Container<T>::ContainedItem::getItem () const {
> * * * * return &item_;
>
> }
>
> === END ===
>
> Now, my problem is very specific: When T is an arbitrary type I want
> Container<T>::ContainedItem::getItem() to return a const T *, just
> like it already does. However, when T specifically is a
> boost::shared_ptr<X>, I want Container<T>::ContainedItem::getItem() to
> return a const X *, not a const T *. For example:
>
> === BEGIN ===
>
> #include <boost/shared_ptr.hpp>
> using boost::shared_ptr;
>
> int main () {
> * * * * Container<Object> x;
> * * * * Container<shared_ptr<Object> > y;
> * * * * x.setData(Object()); // i want this
> * * * * y.setData(shared_ptr<Object>()); // i want this
> * * * * x.getData().getItem()->function(); // i want this
> * * * * y.getData().getItem()->get()->function(); // don't want this!
> * * * * //y.getData().getItem()->function(); // i want this instead!
>
> }
>
> === END ===


Note that
template <typename T> const T * Container< shared_ptr<T>
>::ContainedItem::

getItem () const

is a partial specialization of the member function getItem, and you
cannot partially specialize member function of class templates. To
avoid having to specialize the entire class template, you could
perhaps do something like this:

template<typename T> struct ContainerTraits {
typedef const T * ReturnType;
static ReturnType get(const T& t) { return &t; }
};

template<typename T> struct ContainerTraits< shared_ptr<T> > {
typedef const T * ReturnType;
static ReturnType get(const shared_ptr<T>& p) { return p.get(); }
};

// declaration of getItem:
typename ContainerTraits<T>::ReturnType getItem () const;

// definition of getItem:
template <typename T> typename ContainerTraits< T >::ReturnType
Container<T>::ContainedItem::getItem () const {
return ContainerTraits<T>::get(item_);
}

int main() {
Container<Object>().getData().getItem()->function(); // ok
Container< shared_ptr<Object> >().getData().getItem()->function
(); // ok
}
 
Reply With Quote
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      12-05-2008
On Dec 5, 2:28*am, Triple-DES <DenPlettf...@gmail.com> wrote:
> On 5 Des, 06:25, "jason.cipri...@gmail.com" <jason.cipri...@gmail.com>
> wrote:
>
>
>
> > === BEGIN ===

>
> > // An example object with a member function.
> > class Object {
> > public:
> > * * * * void function () const { }

>
> > };

>
> > template <typename T> class Container {
> > private:
> > * * * * T data_; // Container's instance of the data.
> > public:
> > * * * * // This just wraps an item.
> > * * * * class ContainedItem {
> > * * * * private:
> > * * * * * * * * T item_; // Some copy of the data.
> > * * * * public:
> > * * * * * * * * explicit ContainedItem (const T &item) : item_(item) { }
> > * * * * * * * * const T * getItem () const; // This gets the copy.
> > * * * * };
> > * * * * // Get via ContainedItem.
> > * * * * ContainedItem getData () const { return ContainedItem(data_); }
> > * * * * // Set value directly.
> > * * * * void setData (const T &data) { data_ = data; }

>
> > };

>
> > // Generic template implementation.
> > template <typename T>
> > const T * Container<T>::ContainedItem::getItem () const {
> > * * * * return &item_;

>
> > }

>
> > === END ===

>
> > Now, my problem is very specific: When T is an arbitrary type I want
> > Container<T>::ContainedItem::getItem() to return a const T *, just
> > like it already does. However, when T specifically is a
> > boost::shared_ptr<X>, I want Container<T>::ContainedItem::getItem() to
> > return a const X *, not a const T *. For example:

>
> > === BEGIN ===

>
> > #include <boost/shared_ptr.hpp>
> > using boost::shared_ptr;

>
> > int main () {
> > * * * * Container<Object> x;
> > * * * * Container<shared_ptr<Object> > y;
> > * * * * x.setData(Object()); // i want this
> > * * * * y.setData(shared_ptr<Object>()); // i want this
> > * * * * x.getData().getItem()->function(); // i want this
> > * * * * y.getData().getItem()->get()->function(); // don't want this!
> > * * * * //y.getData().getItem()->function(); // i want this instead!

>
> > }

>
> > === END ===

>
> Note that
> template <typename T> const T * Container< shared_ptr<T>>::ContainedItem::
>
> getItem () const
>
> is a partial specialization of the member function getItem, and you
> cannot partially specialize member function of class templates. To
> avoid having to specialize the entire class template, you could
> perhaps do something like this:
>
> template<typename T> struct ContainerTraits {
> * typedef const T * ReturnType;
> * *static ReturnType get(const T& t) { return &t; }
>
> };
>
> template<typename T> struct ContainerTraits< shared_ptr<T> > {
> * typedef const T * ReturnType;
> * static ReturnType get(const shared_ptr<T>& p) *{ return p.get(); }
>
> };
>
> // declaration of getItem:
> typename ContainerTraits<T>::ReturnType getItem () const;
>
> // definition of getItem:
> template <typename T> typename ContainerTraits< T >::ReturnType
> Container<T>::ContainedItem::getItem () const {
> * return ContainerTraits<T>::get(item_);
>
> }
>
> int main() {
> * Container<Object>().getData().getItem()->function(); // ok
> * Container< shared_ptr<Object> >().getData().getItem()->function
> (); // ok
>
> }



Oh, I think I get it, that's pretty neat. So... the purpose of
ContainerTraits is to take anything you'd need to specialize out of a
member function that can't be partially specialized, and move it into
a class that can be? And also, I guess it can simplify more complex
templates by letting you use, say, ContainerTraits<T>::ReturnType
everywhere instead of having to make specializations all over the
place.

Thanks,
Jason
 
Reply With Quote
 
Triple-DES
Guest
Posts: n/a
 
      12-05-2008
On 5 Des, 09:16, "jason.cipri...@gmail.com" <jason.cipri...@gmail.com>
wrote:
> On Dec 5, 2:28*am, Triple-DES <DenPlettf...@gmail.com> wrote:


> Oh, I think I get it, that's pretty neat. So... the purpose of
> ContainerTraits is to take anything you'd need to specialize out of a
> member function that can't be partially specialized, and move it into
> a class that can be? And also, I guess it can simplify more complex
> templates by letting you use, say, ContainerTraits<T>::ReturnType
> everywhere instead of having to make specializations all over the
> place.
>


Yes, in fact I made the trait class just for the return type. Then I
realized that the logic for getting the T* had to be specialized as
well. I suppose the class template could be turned into a full-fledged
function object, since it is no longer a pure "traits" class
(according to some definitions of the term).

I think it is a fairly common approach to delegate to a function
object when you want something like partial specialization for a
function template (or a member function of a template). At least I
have done this myself occasionally.
 
Reply With Quote
 
jason.cipriani@gmail.com
Guest
Posts: n/a
 
      12-05-2008
On Dec 5, 6:09*am, Triple-DES <DenPlettf...@gmail.com> wrote:
> On 5 Des, 09:16, "jason.cipri...@gmail.com" <jason.cipri...@gmail.com>
> wrote:
>
> > On Dec 5, 2:28*am, Triple-DES <DenPlettf...@gmail.com> wrote:
> > Oh, I think I get it, that's pretty neat. So... the purpose of
> > ContainerTraits is to take anything you'd need to specialize out of a
> > member function that can't be partially specialized, and move it into
> > a class that can be? And also, I guess it can simplify more complex
> > templates by letting you use, say, ContainerTraits<T>::ReturnType
> > everywhere instead of having to make specializations all over the
> > place.

>
> Yes, in fact I made the trait class just for the return type. Then I
> realized that the logic for getting the T* had to be specialized as
> well. I suppose the class template could be turned into a full-fledged
> function object, since it is no longer a pure "traits" class
> (according to some definitions of the term).
>
> I think it is a fairly common approach to delegate to a function
> object when you want something like partial specialization for a
> function template (or a member function of a template). At least I
> have done this myself occasionally.


Cool, thanks for the help!

Jason
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
decltype as a template parameter when containing reference to anothertemplate parameter. Isti C++ 2 04-19-2010 10:01 PM
how to partially specialize a template class nested inside anothertemplate class? huili80@gmail.com C++ 5 06-22-2008 01:47 PM
How to do explicit specialization of non-type template function Bill C++ 7 02-22-2008 11:57 AM
Explicit specialization of member class template Barry C++ 2 09-30-2007 04:42 AM
What's the difference betwwen explicit instantiaion and explicit specialization? Andy C++ 5 01-30-2005 11:46 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57